require "Common/EnumConst"
require "Battle/Entity/Entity"
require "Battle/FightEntity"
require "Battle/Entity/PetEntity"
require "Battle/Manager/SpineEffectManager"
require "Battle/BattleScene"
require "Battle/Manager/ClientFightManager"

---@class FightMgr
FightManager = {}
FightMgr = {}
setmetatable(FightManager, {
    __index = function(mytable, key)
        if logicMgr.FightSelect.isShowSaveReport then
            return ClientFightManager[key];
        else
            return FightMgr[key];
        end

    end,
    __newindex = function(mytable, key, value)
        if logicMgr.FightSelect.isShowSaveReport then
            ClientFightManager[key] = value;
        else
            FightMgr[key] = value;
        end
    end
})
local prepareTime = {
    ["70212400"] = 792,
    ["70218400"] = 792,
    ["70462400"] = 957,
    ["70468400"] = 957,
    ["70472400"] = 99,
    ["70478400"] = 99,
    ["70482400"] = 1584,
    ["70488400"] = 1584,
    ["82400"] = 660,
    ["88400"] = 660,
    ["502400"] = 1815,
    ["508400"] = 1815,
    ["522400"] = 726,
    ["528400"] = 726,
    ["542400"] = 231,
    ["542408"] = 231,
    ["70542400"] = 231,
    ["70548400"] = 231,
    ["70632400"] = 363,
}
local this = FightMgr;
local defaultFrame = EnumConst.FIGHT_FRAME / EnumConst.THOUSANDTH
this.cameraMain = nil;
this.cameraMainControllerParam = nil;
this.maxFrame = 0;
this.maxTime = 0;
this.keyIndex = {}
this.isShowBattleInfo = false;
this.modelID = nil
this.modeVal = nil
this.preEntranceFinished = false;
this.loadingFinished = false;
this.hasInit = true;
this.hasEntrance = false;
this.handle = nil;
this.reportStr = "";
this.fightType = 0;
this.tFightType = 0;
this.fighterList = {};
this.fighterMap = {};
this.initFighterList = {};
this.initSkillList = {};
this.commandList = {};
this.hitDataList = {};
this.damageDataList = {};
this.skillPositionList = {};--技能定点位置
this.resList = {};
this.starTime = 0;
this.lastTime = 0;
this.gameTime = 0;
this.frame = 0;
this.mapInstanse = nil;
this.alternateDelay = 1;--替补入场延时。
this.battleInfo = {};
this.cacheJumpWord = {};
this.helpManFightId = {};--援助者fightId
this.mainFormationFightId = {};

--cutin
this.cutInState = false;
this.cutInTime = 0;
this.cutInSkillTime = 0;
this.cutInCmdList = {};
this.cutInFighterId = 0;

this.resultItems = {};
this.fightResult = 0;
--战斗加速
this.logicLoop = 1;
this.decimalAccumulation = 0;
this.integralPart = 0;
--时间缩放
this.curTimeScale = 1;
this.timeScaleEntranceLv_1 = 1.75 --一倍速度的进场速度
this.timeScaleLv_1 = 1;--一档不可加速
this.timeScaleLv_2 = 1.75;--加速二档，界面显示x2
this.timeScaleLv_3 = 4.25;--加速三档，界面显示x5
this.cutinDecimalAccumulation = 0

this.bossScale = 1.7;

this.pet_1 = nil;
this.pet_2 = nil;

--玩家死亡后，暂时未回收的特效，在此暂存
this.effectTempCacheList = {};

----放技能减速
--this.slowTime = 0;
--this.slowTimeState = false;
--this.slowTimeFactor = 0.3; --减速系数
--this.slowTimeDuration = 330; --减速时间

--test
this.printMsg = "";
this.fighterDamage = {};
this.fighterHP = {};
this.fighterEndDamage = {};
this.fighterEndHP = {};
this.targetFighterId = 8;
this.targetDamage = 0;
this.targetDamage2 = 0;
this.testDamage = {}
this.commandDamageList = {}--不走帧事件的伤害堆栈
this.alternate = {};
this.FightDebug = true;
this.deadFormation = {};--记录大秘境死亡的角色id
this.myKills = {};

--this.testTime=0;
----战斗角色模型大小，统一缩放，在挂机界面已经缩小后0.8后，又一次缩放
this.scaleParam = 0.8;
this.hideSelfDamage = true; --默认true
this.showFrame = false;
this.isRePlay = false
this.replay_type = nil
this.isDungeonWinRePlay = false

--Debug用参数
this.saveReport = false;--不要赋值为true，更不要上传true;

this.skeletonAnimStateUserDataString = {}

--记录所有类型战斗的最新战斗结果
this.BattleResultDic = {}
---@return 是否是挂机战斗
--this.IsBattleFight = false
--队伍重定位（暂时只有排位战使用）
this.teamRest = {};

--战斗结束标签 在所有敌人指令动作执行完成后 如果战斗结束标签为true 则执行结束逻辑
this.endTag = false;
this.endTimer = nil;--收到游戏结束帧后3秒后强制游戏结束
this.endTime = 1000
this.myModelds = {}
--游戏结束
this.gameEnd = false
--当前渲染帧
this.frameRander = 0
this.loadContentId = {}
--延时（为了解决cutIn导致延时时机不对的bug）
this.delayFuncs = {}--延时的方法
this.delayFuncsTime = {}--延时的方法延时时间
this.updateFunc = {};
this.updateFuncTime = {};
this.delayBeCutInFuncs = {}--延时的方法(无视子弹时间）
this.delayBeCutInFuncsTime = {}--延时的方法延时时间(无视子弹时间）
this.updateBeCutInFunc = {}--update方法(无视子弹时间）
this.updateBeCutInFuncTime = {} --update方法持续时间(无视子弹时间）
this.damageTemp = {};
this.skinId2Fighter = {}--根据fighterId取到

this.isSkillEditor = false;--是否是技能编辑器
this.sceneEffectObj = nil
this.supSkillCutIn = false;--援助技能cutin
this.supSkillTempTime = 1;--存储的当前加速
this.supTimeScale = {
    [1] = 1, --1倍速时间缩放
    [1.75] = 1, --2倍速时间缩放
    [4.25] = 1.75, --5倍速时间缩放
}
this.battleFunction = nil
this.automaticSkills = false;--是否自动技能
this.fighterAndEntityList = {}--根据model取得fighter类和entity类his.battleFunction = nil
this.isAuto = nil
this.autoJump = nil
this.timerId = nil
function FightMgr.init()
    this.preEntranceFinished = false;
    this.loadingFinished = false;
    this.endTag = true;
    this.hasInit = true;
    this.frameRander = 0
    this.handle = nil;
    this.reportStr = "";
    this.fightType = 0;
    this.tFightType = 0
    this.fighterList = {};
    this.fighterMap = {};
    this.initFighterList = {};
    this.initSkillList = {};
    this.commandList = {};
    this.hitDataList = {};
    this.damageDataList = {};
    this.myKills = {};
    this.resList = {};
    this.starTime = 0;
    this.lastTime = 0;
    this.gameTime = 0;
    this.frame = 0;
    this.cutinDecimalAccumulation = 0

    --cutin
    this.cutInState = false;
    this.cutInTime = 0;
    this.cutInSkillTime = 0;
    this.cutInCmdList = {};
    this.cutInFighterId = 0;

    this.fightResult = 0;

    SpineEffectManager.init();
    EnumConst.FIGHT_INNER_ROUND = HelperFunc.GetGlobalVlue(54)

    ShaderEffectManager.init();

    --test
    this.printMsg = "";
    this.fighterDamage = {};
    this.fighterHP = {};
    this.fighterEndDamage = {};
    this.fighterEndHP = {};
    this.targetFighterId = 8;
    this.targetDamage = 0;
    this.targetDamage2 = 0;
    this.testDamage = {}
    this.commandDamageList = {}
    this.alternate = {};
    this.cacheJumpWord = {};
    this.effectTempCacheList = {};
    this.helpManFightId = {};
    this.mainFormationFightId = {};
    this.myModelds = {}
    this.gameEnd = false
    this.loadContentId = {}
    this.delayFuncs = {}--延时的方法
    this.delayFuncsTime = {}--延时的方法延时时间
    this.updateFunc = {};
    this.updateFuncTime = {};
    this.delayBeCutInFuncs = {}--延时的方法(无视子弹时间）
    this.delayBeCutInFuncsTime = {}--延时的方法延时时间(无视子弹时间）
    this.updateBeCutInFunc = {}--update方法(无视子弹时间）
    this.updateBeCutInFuncTime = {} --update方法持续时间(无视子弹时间）
    this.damageTemp = {};
    this.skinId2Fighter = {}--根据fighterId取到
    this.sceneEffectObj = nil;
    this.supSkillCutIn = false;
    this.supSkillTempTime = 1;
    this.supTimeScale = {
        [1] = 1, --1倍速时间缩放
        [1.75] = 1, --2倍速时间缩放
        [4.25] = 1.75, --5倍速时间缩放
    }
    local hide = GetPlayerPrefs("hideSelfDamage")
    if hide then
        FightMgr.hideSelfDamage = tonumber(hide) == 1
    else
        FightMgr.hideSelfDamage = true
    end
    this.linkFunc = nil;
    this.onlyIdByFlyList = {}--根据唯一id取得fly指令
end

function FightMgr.destroy()
    --this.fightType = 0;
    this.tFightType = 0
    this.hasEntrance = false;
    this.hasInit = false;
    this.loadingFinished = false;
    this.preEntranceFinished = false;
    this.gameEnd = false
    this.delayFuncs = {}--延时的方法
    this.delayFuncsTime = {}--延时的方法延时时间
    this.updateFunc = {}--update方法
    this.updateFuncTime = {} --update方法持续时间
    this.delayBeCutInFuncs = {}--延时的方法(无视子弹时间）
    this.delayBeCutInFuncsTime = {}--延时的方法延时时间(无视子弹时间）
    this.updateBeCutInFunc = {}--update方法(无视子弹时间）
    this.updateBeCutInFuncTime = {} --update方法持续时间(无视子弹时间）
    this.damageTemp = {};
    this.skinId2Fighter = {}--根据fighterId取到
    this.sceneEffectObj = nil;
    this.supSkillCutIn = false;
    this.supSkillTempTime = 1;
    for i = 1, #this.fighterList do
        this.fighterList[i]:RemoveSkillEffect();
        this.fighterList[i]:destroy();
    end
    if this.pet_1 then
        this.pet_1:destroy();
        this.pet_1 = nil;
    end
    if this.pet_2 then
        this.pet_2:destroy();
        this.pet_2 = nil;
    end
    BattleSceneCacheResouce:RemoveMapFromParent()
    for index, effect in pairs(this.effectTempCacheList) do
        if effect then
            effect:stop();
        end
        this.effectTempCacheList[index] = nil;
    end
    this.effectTempCacheList = {};
    SpineEffectManager.clearAllEff();
    EffectManager.clearAllEff();
    for k, v in pairs(this.cacheJumpWord) do
        if v then
            UIBloodBar.RemoveBloodFly(v);
        end
    end
    this.cacheJumpWord = {};
    local battleRoundRoot = panelMgr.BattleRound;
    if battleRoundRoot ~= nil then
        local count = battleRoundRoot.transform.childCount;
        if count > 0 then
            for i = 0, count - 1 do
                local child = battleRoundRoot.transform:GetChild(i);
                if not BattleSceneCacheResouce:IsCacheObj(child.gameObject) then
                    destroy(child.gameObject);
                end
            end
        end
    end

    this.fighterList = {};
    if this.handle then
        UpdateBeat:Remove(this.update, this)
        --FixedUpdateBeat:Remove(this.update,this)

        this.handle = nil;
    end
    this.handle = nil
    this.reportStr = "";
    --this.fightType = 0;
    this.fighterMap = {};
    this.initFighterList = {};
    this.commandList = {};
    this.hitDataList = {};
    this.damageDataList = {};
    this.resList = {};
    this.skeletonAnimStateUserDataString = {}
    --HelperFunc.UnloadUnusedAssets(EnumConst.ClearType.Fight)
end

function FightMgr.UpdateResTime()
    resMgr:ClearBattleResRef()
    for k, v in pairs(this.resList) do
        resMgr:UpdateResTime(k, v)
    end

    local heroID = logicMgr.HeroManager.GetRoleHeadID()
    local useSkinId = logicMgr.SkinManager.getHeroSkinId(heroID)
    local path = HeroManager.GetHeroDrawingRolePath(heroID, nil, useSkinId);

    resMgr:UpdateResTime(path, "Model")

    local mapId = tostring(logicMgr.MapManager.getMapId());
    local mapName = logicMgr.MapManager.getBattleMapName();
    resMgr:UpdateResTime("Prefabs/MapPref/" .. mapName, "Map")
end

function FightMgr.update(dt)
    if not this.cutInState then
        this.starTime = this.starTime + Time.deltaTime;
        if this.starTime - this.lastTime >= EnumConst.FIGHT_FRAME / EnumConst.THOUSANDTH then
            this.integralPart = Mathf.Floor(Time.timeScale);
            this.logicLoop = this.integralPart;
            if this.integralPart ~= Time.timeScale then
                this.decimalAccumulation = this.decimalAccumulation + Time.timeScale - this.integralPart;
                if this.decimalAccumulation >= 1 then
                    this.decimalAccumulation = this.decimalAccumulation - 1;
                    this.logicLoop = this.logicLoop + 1;
                end
            end
            for i = 1, this.logicLoop do
                this.updateLogicFrame();
            end
            this.lastTime = this.lastTime + EnumConst.FIGHT_FRAME / EnumConst.THOUSANDTH;
        end
    else
        this.cutinStartTime = this.cutinStartTime or 0
        this.lastCutinTime = this.lastCutinTime or 0
        this.cutinStartTime = this.cutinStartTime + Time.deltaTime
        if this.cutinStartTime - this.lastCutinTime >= EnumConst.FIGHT_FRAME / EnumConst.THOUSANDTH then
            this.cutinIntegralPart = Mathf.Floor(Time.timeScale);
            this.cutinLogicLoop = this.cutinIntegralPart;
            if this.cutinIntegralPart ~= Time.timeScale then
                this.cutinDecimalAccumulation = this.cutinDecimalAccumulation + Time.timeScale - this.cutinIntegralPart;
                if this.cutinDecimalAccumulation >= 1 then
                    this.cutinDecimalAccumulation = this.cutinDecimalAccumulation - 1;
                    this.cutinLogicLoop = this.cutinLogicLoop + 1;
                end
            end
            for i = 1, this.cutinLogicLoop do
                this.updateLogicFrame();
            end
            this.lastCutinTime = this.lastCutinTime + EnumConst.FIGHT_FRAME / EnumConst.THOUSANDTH;
        end
    end
    if not this.cutInState then
        local time = Mathf.Floor((this.frame + 1) * EnumConst.FIGHT_FRAME / EnumConst.THOUSANDTH);
        FireEvent(Config.EventType.Fight_Update_Time, maxTime - time);
        if this.linkFunc then
            --钩子效果
            this.linkFunc()
        end
        for i, v in pairs(this.updateFuncTime) do
            this.updateFuncTime[i] = v - Time.deltaTime;
            this.updateFunc[i](this.updateFuncTime[i]);
            if this.updateFuncTime[i] <= 0 then
                this.updateFuncTime[i] = nil;
                this.updateFunc[i] = nil;
            end
        end

        for i, v in pairs(this.delayFuncsTime) do
            this.delayFuncsTime[i] = v - Time.deltaTime;
            if v <= 0 then
                this.delayFuncs[i]();
                this.delayFuncs[i] = nil;
                this.delayFuncsTime[i] = nil;
            end
        end

    else
        for i, v in pairs(this.updateBeCutInFuncTime) do
            this.updateBeCutInFuncTime[i] = v - Time.deltaTime;
            this.updateBeCutInFunc[i](this.updateBeCutInFuncTime[i]);
            if this.updateBeCutInFuncTime[i] <= 0 then
                this.updateBeCutInFuncTime[i] = nil;
                this.updateBeCutInFunc[i] = nil;
            end
        end

        for i, v in pairs(this.delayBeCutInFuncsTime) do
            this.delayBeCutInFuncsTime[i] = v - Time.deltaTime;
            if v <= 0 then
                this.delayBeCutInFuncs[i]();
                this.delayBeCutInFuncs[i] = nil;
                this.delayBeCutInFuncsTime[i] = nil;
            end
        end
    end

    this.fighterUpdate()

    --[[
        for i=1,#this.fighterList do
            local fighter = this.fighterList[i];
            if fighter.hp <= 0 and not fighter:getDeadState() then
                fighter:setDead();
                FireEvent(Config.FightEvent.ROLE_DEAD,fighter);
            end
        end
    ]]

    --logMy('逻辑帧',this.frame,'渲染帧',this.frameRander,'Time.deltaTime', Time.deltaTime)
end

function FightMgr.fighterUpdate()
    for i = 1, #this.fighterList do
        local fighter = this.fighterList[i];
        if not this.cutInState then
            fighter:onUpdate(Time.deltaTime);

        elseif not supSkillCutIn then
            if this.cutInFighterId == fighter.fighterId or fighter.isDead or fighter.isDeading or fighter.hp <= 0 then
                fighter:onUpdate(Time.deltaTime);
            end
        end
    end
    if this.pet_1 then
        this.pet_1:onUpdate(Time.deltaTime);
    end
    if this.pet_2 then
        this.pet_2:onUpdate(Time.deltaTime);
    end
    if not this.cutInState then
        this.frameRander = this.frameRander + 1
    end
end

function FightMgr.updateLogicFrame()

    if this.cutInState then
        this.updateFrameCutIn(defaultFrame * this.curTimeScale);
    else
        this.updateFrame(this.frame);
        this.gameTime = this.gameTime + defaultFrame * this.curTimeScale;
        this.frame = this.frame + 1;
    end
end

function FightMgr.readReport(report, type, fightResult)

    this.fightType = type;
    this.tFightType = type
    if (this.tFightType == 3 or this.tFightType == 22) and logicMgr.ArenaManager.getSomeBattleSkip() then
        this.tFightType = 0
    end
    this.reportStr = report;--decodeJsonStrToTabel(report);
    if fightResult ~= nil then
        --兼容以前
        this.fightResult = fightResult
    end
    this.analyseReport();
    --this.testTime = Time.realtimeSinceStartup;
    if type == EnumConst.FightTypeConst.DUNGEON then
        maxTime = logicMgr.MapManager.getMaxTime();
    elseif type == EnumConst.FightTypeConst.TOWER then
        maxTime = logicMgr.MapManager.getMaxTime();
    elseif type == EnumConst.FightTypeConst.ARENA then
        maxTime = logicMgr.MapManager.getMaxTime();
    elseif type == EnumConst.FightTypeConst.TRIAL then
        -- maxTime = logicMgr.MapManager.getMaxTime();
        local battleRecord = BattlePlaybackManager.getBattleRecord() or {}
        local maxBattleSeconds = battleRecord.maxBattleSeconds or 0
        maxTime = maxBattleSeconds == 0 and logicMgr.MapManager.getMaxTime() or maxBattleSeconds
    else
        maxTime = 90
    end

    FireEvent(Config.EventType.AddLoadingLoadResource, this.resList)
end

function FightMgr.PreloadBattleSceneRes()

    local battleSceneResList = UILoading.GetLoadModelResList()--BattleScene.GetResList()
    if battleSceneResList ~= nil then
        for i = 1, #battleSceneResList do
            local array = string.split(battleSceneResList[i], "#")
            if #array > 1 then
                if array[2] == "Effect" then
                    this.resList[array[1]] = "Model"
                else
                    this.resList[array[1]] = array[2]
                end
            end
        end
    end

    if UIBattleTeam ~= nil then
        local mapName = UIBattleTeam.GetMapName()
        if mapName ~= nil then
            this.resList[mapName] = "Map"
        end
    end

    local heroID = logicMgr.HeroManager.GetRoleHeadID()
    local useSkinId = logicMgr.SkinManager.getHeroSkinId(heroID)
    local path = HeroManager.GetHeroDrawingRolePath(heroID, nil, useSkinId);

    this.resList[path] = "Model"
end

function FightMgr.SetRePlay(replay)

    this.isRePlay = replay
    this.replay_type = nil
end

function FightMgr.GetReplay(replay)

    return this.isRePlay
end

function FightMgr.SetReplayType(_type)

    this.replay_type = _type
end

function FightMgr.GetReplayType(_type)

    return this.replay_type
end

function FightMgr.SetDungeonWinRePlay(value)

    this.isDungeonWinRePlay = value;
end
function FightMgr.GetDungeonWinRePlay()

    return this.isDungeonWinRePlay;
end

function FightMgr.analyseReport()

    this.maxFrame = 0;
    local countCom = 0
    local hitIgnore = {}--{key onlyId,value targetId}
    for k, v in pairs(this.reportStr) do
        --logMy('countCom',countCom)
        local frame = toNumber(v["1"]);
        local action = toNumber(v["2"]);
        local type = toNumber(v["3"]);
        local value = v["4"];
        if action == EnumConst.FightActionType.INIT then
            local fighterId = value["1"];
            local modelId = value["2"];
            local maxHP = value["3"];
            local hp = value["4"];
            local maxEnergy = value["5"];
            local energy = value["6"];
            local teamIndex = toNumber(value["7"]);
            if teamIndex > 0 then
                teamIndex = 2;
            else
                teamIndex = 1;
            end
            local position = value["8"];
            local weaponLevel = value["9"];
            local skinId = value["10"]
            logicMgr.SoloChaosTestManager.setMaxHp(maxHP);
            SoloChaosTestManager.setBossId(modelId);
            if skinId == nil or skinId == 0 or G.dataTable["t_skin"][tostring(skinId)].f_SkinType == 0 then
                skinId = nil
            else
                this.skinId2Fighter[fighterId] = skinId;
            end
            if this.mainFormationFightId[teamIndex] == nil then
                this.mainFormationFightId[teamIndex] = {};
            end
            local param = {};
            param.fighterId = fighterId;
            param.modelId = modelId;
            if modelId ~= 0 then
                table.insert(this.mainFormationFightId[teamIndex], param);
            end

            this.addFighter(fighterId, modelId, teamIndex, maxHP, hp, maxEnergy, energy, position, type, weaponLevel, true, false, skinId);
            local commandInfo = {};
            commandInfo.frame = frame;
            commandInfo.action = action;
            commandInfo.type = type;
            commandInfo.fighterId = fighterId;
            commandInfo.position = position;
            this.addCommand(frame, commandInfo);

            if this.FightDebug then
                local x = position["1"];
                local z = position["2"];
                fightShowLog("[INIT]fighterId:" .. fighterId .. " modelId:" .. modelId .. " hp:" .. hp .. "/" .. maxHP .. " mp:" .. energy .. "/" .. maxEnergy .. " pos:" .. x .. "," .. z);
                this.fighterHP[fighterId] = maxHP;
            end
        elseif action == EnumConst.FightActionType.ATTACK then
            local fighterId = value["1"];
            local targetId = value["2"];
            local skillId = value["3"];
            local attackSpeed = value["4"];
            local skillFixedPos = value["7"];
            local skillOnlyId = value["10"];
            --local actionFrame = value["4"];
            local actionPos = value["5"];
            --local skillShow = value["6"];
            local commandInfo = {};
            commandInfo.frame = frame;
            commandInfo.action = action;
            commandInfo.type = type;
            commandInfo.fighterId = fighterId;
            commandInfo.targetId = targetId;
            commandInfo.skillId = skillId;
            commandInfo.skillFixedPos = skillFixedPos;
            commandInfo.skillOnlyId = skillOnlyId
            commandInfo.actionPos = actionPos;
            local weaponSkill = G.dataTable["t_armskill"][tostring(skillId)];
            local skillShow = G.dataTable["t_skillshow"][tostring(skillId)];
            if skillShow == nil and weaponSkill then
                skillShow = G.dataTable["t_skillshow"][tostring(weaponSkill["f_ArmSkillReal"])];
                skillId = weaponSkill["f_ArmSkillReal"];
            end
            local isAdd = true;
            if not skillShow then
                logMy('@策划skillshow not found. skillId = ' .. skillId);
                isAdd = false;
            end
            if isAdd then
                commandInfo.skillShow = skillShow;
                commandInfo.attackSpeed = attackSpeed;
                this.addSkill(skillId, skillShow);
                if skillShow and skillShow.f_overhit then
                    local overHit = G.dataTable["t_skillshow"][tostring(skillShow.f_overhit)];
                    this.addSkill(skillShow.f_overhit, overHit);
                end
                local supSkillId = FightMgr.battleInfo.mySupSkill;

                if skillId == supSkillId and FightMgr.battleInfo.myHelpPartnerModelId == nil then
                    local supSkillShowInfo = {};
                    supSkillShowInfo.frame = frame - 15;
                    supSkillShowInfo.action = EnumConst.FightActionType.SUPSKILLSHOW;
                    local doFrame = 1;
                    if frame - 15 > 1 then
                        doFrame = frame - 15;
                    end
                    this.addCommand(doFrame, supSkillShowInfo);

                end
                this.addCommand(frame, commandInfo);
            end
        elseif action == EnumConst.FightActionType.MOVE then
            local fighterId = value["1"];
            local endframe = value["2"];
            local position = value["3"];
            local commandInfo = {};
            commandInfo.frame = frame;
            commandInfo.action = action;
            commandInfo.type = type;
            commandInfo.fighterId = fighterId;
            commandInfo.endframe = endframe;
            commandInfo.position = position;
            this.addCommand(frame, commandInfo);
        elseif action == EnumConst.FightActionType.CHANGE_POINT then
            local fighterId = value["1"];
            local subType = value["2"] or 0;--2拖过来
            local position = value["3"];
            local targetId = value["4"];
            local finishFrame = tonumber(value["5"]) or frame
            local high = tonumber(value["6"])
            local commandInfo = {};
            commandInfo.frame = frame;
            commandInfo.action = action;
            commandInfo.type = type;
            commandInfo.fighterId = fighterId;
            commandInfo.position = position;
            commandInfo.targetId = targetId;
            commandInfo.subType = subType
            commandInfo.finishFrame = finishFrame
            commandInfo.high = high
            this.addCommand(frame, commandInfo);
        elseif action == EnumConst.FightActionType.HIT then
            local fighterId = value["1"];
            local targetId = value["2"];
            local skillId = value["3"];
            local skillShow = value["5"];
            local skillOnlyId = value["10"];
            local weaponSkill = G.dataTable["t_armskill"][tostring(skillId)];
            skillShow = G.dataTable["t_skillshow"][tostring(skillId)];
            if skillShow == nil and weaponSkill then
                skillShow = G.dataTable["t_skillshow"][tostring(weaponSkill["f_ArmSkillReal"])];
                skillId = weaponSkill["f_ArmSkillReal"];
            end
            local isAdd = true;
            if not skillShow then
                logMy('@策划skillshow not found. skillId = ' .. skillId);
                isAdd = false;
            end
            if isAdd then
                if skillShow and skillShow.f_IncidentTakeEffect and skillShow.f_IncidentTakeEffect ~= "" and skillShow.f_IncidentTakeEffect > 0 then
                    local commandInfo = {};
                    commandInfo.frame = frame;
                    commandInfo.action = EnumConst.FightActionType.HIT;
                    commandInfo.type = type;
                    commandInfo.fighterId = fighterId;
                    commandInfo.targetId = targetId;
                    commandInfo.skillId = skillId;
                    commandInfo.skillOnlyId = skillOnlyId;
                    this.addCommand(frame, commandInfo);
                else
                    local hitInfo = {};
                    hitInfo.fighterId = fighterId;
                    hitInfo.targetId = targetId;
                    hitInfo.skillId = skillId;
                    hitInfo.frame = frame;
                    hitInfo.skillShow = skillShow;
                    hitInfo.skillOnlyId = skillOnlyId;
                    if skillShow.f_HitFResource == "fxh061f" and skillShow.f_HitFName == "skill2_hit" then
                        local ignore = hitIgnore[skillOnlyId];
                        if ignore == nil then
                            hitIgnore[skillOnlyId] = targetId;
                            this.addHit(frame, hitInfo);
                        else
                            if ignore ~= targetId then
                                this.addHit(frame, hitInfo);
                            end
                        end
                    else
                        this.addHit(frame, hitInfo);
                    end
                end
            end
        elseif action == EnumConst.FightActionType.DAMAGE then
            if type == EnumConst.DamageType.NONE then
                local fighterId = value["1"];
                local targetId = value["2"];
                local damage = value["3"];
                local damageType = value["4"];
                local skillId = value["5"];
                local skillFrame = value["6"];
                local skillOnlyId = value["10"];
                local skillShow = G.dataTable["t_skillshow"][tostring(skillId)];
                local skillInfo = G.dataTable["t_skill"][tostring(skillId)];
                local weaponSkill = G.dataTable["t_armskill"][tostring(skillId)];
                if skillInfo == nil and weaponSkill then
                    skillInfo = G.dataTable["t_skill"][tostring(weaponSkill["f_ArmSkillReal"])];
                    skillId = weaponSkill["f_ArmSkillReal"]
                end
                if skillShow == nil and weaponSkill then
                    skillShow = G.dataTable["t_skillshow"][tostring(weaponSkill["f_ArmSkillReal"])];
                    skillId = weaponSkill["f_ArmSkillReal"]
                end
                local addDamage = true;

                if not skillShow then
                    logMy('@策划 skillshow not found. skillId = ' .. skillId);
                    addDamage = false;
                end
                if not skillInfo then
                    logMy('@策划 skillInfo not found. skillId = ' .. skillId);
                    addDamage = false;
                end

                local damageInfo = {};
                if addDamage then
                    if this.onlyIdByFlyList[skillOnlyId] and skillShow.f_IncidentTakeEffect > 0 then
                        this.onlyIdByFlyList[skillOnlyId].endTime = frame;
                    end
                    if damage == 0 and damageType == Config.damageType.normal then
                    elseif skillId < 1000 then
                    elseif skillShow and skillShow.f_IncidentTakeEffect > 0 then
                        local commandInfo = {};
                        commandInfo.frame = frame;
                        commandInfo.action = action;
                        commandInfo.type = type;
                        commandInfo.fighterId = fighterId;
                        commandInfo.targetId = targetId;
                        commandInfo.damage = damage;
                        commandInfo.damageType = damageType;
                        commandInfo.skillId = skillId;
                        commandInfo.skillOnlyId = skillOnlyId;

                        damageInfo.fighterId = fighterId;
                        damageInfo.targetId = targetId;
                        damageInfo.damage = damage;
                        damageInfo.damageType = damageType;
                        damageInfo.skillId = skillId;
                        damageInfo.frame = frame;
                        damageInfo.skillOnlyId = skillOnlyId;
                        damageInfo.used = false;
                        if this.commandDamageList[targetId] == nil then
                            this.commandDamageList[targetId] = {};
                        end
                        if this.commandDamageList[targetId][frame] == nil then
                            this.commandDamageList[targetId][frame] = {};
                        end
                        table.insert(this.commandDamageList[targetId][frame], damageInfo);
                        this.addCommand(frame, commandInfo);--战斗帧触发伤害
                    elseif damageType ~= Config.damageType.none then
                        if damageType ~= Config.damageType.sp then
                            damageInfo.fighterId = fighterId;
                            damageInfo.targetId = targetId;
                            damageInfo.damage = damage;
                            damageInfo.damageType = damageType;
                            damageInfo.skillId = skillId;
                            damageInfo.frame = frame;
                            damageInfo.skillOnlyId = skillOnlyId;
                            damageInfo.used = false;
                            if skillFrame ~= nil then
                                damageInfo.skillFrame = skillFrame;
                            else
                                damageInfo.skillFrame = 0;
                            end
                            this.addDamage(frame, damageInfo);--帧动画触发
                            table.insert(this.testDamage, damageInfo);
                        else
                            local commandInfo = {};
                            commandInfo.frame = frame;
                            commandInfo.action = action;
                            commandInfo.type = type;
                            commandInfo.fighterId = fighterId;
                            commandInfo.targetId = targetId;
                            commandInfo.damage = damage;
                            commandInfo.damageType = damageType;
                            commandInfo.skillId = skillId;
                            commandInfo.skillInfo = skillInfo;
                            this.addCommand(frame, commandInfo);--战斗帧触发伤害
                        end
                    end
                    if damageType == Config.damageType.normal or damageType == Config.damageType.crit then
                        this.fighterDamage[targetId] = this.fighterDamage[targetId] or 0;
                        this.fighterDamage[targetId] = this.fighterDamage[targetId] + damage;
                    elseif damageType == Config.damageType.heal then
                        this.fighterDamage[targetId] = this.fighterDamage[targetId] or 0;
                        this.fighterDamage[targetId] = this.fighterDamage[targetId] - damage;
                    end
                    if targetId == this.targetFighterId then
                        if damageType == Config.damageType.normal or damageType == Config.damageType.crit then
                            this.targetDamage = this.targetDamage + damage;
                        elseif damageType == Config.damageType.heal then
                            this.targetDamage = this.targetDamage - damage;
                        end
                        fightShowLog("[Test]frame:" .. frame .. " targetDamage:" .. this.targetDamage);
                    end
                end
            elseif type == EnumConst.DamageType.REAL then
                local fighterId = value["1"];
                local targetId = value["2"];
                local damage = value["3"];
                local damageType = value["4"];
                --local skillId = value["5"];
                local commandInfo = {};
                commandInfo.frame = frame;
                commandInfo.action = action;
                commandInfo.type = type;
                commandInfo.fighterId = fighterId;
                commandInfo.targetId = targetId;
                commandInfo.damage = damage;
                commandInfo.damageType = damageType;
                this.addCommand(frame, commandInfo);
                if damageType == Config.damageType.normal or damageType == Config.damageType.crit then
                    this.fighterDamage[targetId] = this.fighterDamage[targetId] or 0;
                    this.fighterDamage[targetId] = this.fighterDamage[targetId] + damage;
                elseif damageType == Config.damageType.heal then
                    this.fighterDamage[targetId] = this.fighterDamage[targetId] or 0;
                    this.fighterDamage[targetId] = this.fighterDamage[targetId] - damage;
                end
                if targetId == this.targetFighterId then
                    if damageType == Config.damageType.normal or damageType == Config.damageType.crit then
                        this.targetDamage = this.targetDamage + damage;
                    elseif damageType == Config.damageType.heal then
                        this.targetDamage = this.targetDamage - damage;
                    end
                    fightShowLog("[Test]frame:" .. frame .. " targetDamage:" .. this.targetDamage);
                end
            end
        elseif action == EnumConst.FightActionType.FLY then
            local fighterId = value["1"];
            local targetId = value["2"];
            local skillId = value["3"];
            local skillFixedPos = value["4"];
            local realFighter = value["5"];--真实的发起者
            local skillOnlyId = value["10"]
            local skillShow = G.dataTable["t_skillshow"][tostring(skillId)];
            local weaponSkill = G.dataTable["t_armskill"][tostring(skillId)];
            if skillShow == nil and weaponSkill then
                skillShow = G.dataTable["t_skillshow"][tostring(weaponSkill["f_ArmSkillReal"])];
                skillId = weaponSkill["f_ArmSkillReal"];
            end
            if not skillShow then
                logMy('@策划skillshow not found. skillId = ' .. skillId);
                --return
            end
            local commandInfo = {};
            commandInfo.frame = frame;
            commandInfo.action = action;
            commandInfo.type = type;
            commandInfo.fighterId = fighterId;
            commandInfo.targetId = targetId;
            commandInfo.skillId = skillId;
            commandInfo.skillFixedPos = skillFixedPos;
            commandInfo.skillOnlyId = skillOnlyId;
            commandInfo.realFighter = realFighter;
            if skillShow then
                commandInfo.skillShow = skillShow;
                this.addSkill(skillId, skillShow);
                if skillShow and skillShow.f_overhit and skillShow.f_overhit > 0 then
                    local overHit = G.dataTable["t_skillshow"][tostring(skillShow.f_overhit)];
                    if not overHit then
                        logMy('@策划skillshow not found. skillId = ' .. skillShow.f_overhit);
                    else
                        this.addSkill(skillShow.f_overhit, overHit);
                    end
                end
                local showType = toNumber(skillShow.f_SkillShowType);
                if showType ~= EnumConst.AttackShowType.NONE then
                    this.addCommand(frame, commandInfo);
                    this.onlyIdByFlyList[skillOnlyId] = commandInfo;
                end
            end
        elseif action == EnumConst.FightActionType.SKILL_PLAY then
            --设置伤害定点的坐标
            local commandInfo = {};
            local skillId = value["3"];
            local skillFixedPos = value["4"];
            local skillOnlyId = value["10"];

            commandInfo.skillId = skillId;
            commandInfo.skillOnlyId = skillOnlyId;
            commandInfo.skillFixedPos = skillFixedPos;
            this.addPosition(frame, commandInfo);
        elseif action == EnumConst.FightActionType.BUFF then
            local fighterId = value["1"];
            local targetId = value["2"];
            local buffId = value["3"];--typeId
            local buffShow = G.dataTable["t_buffshow"][tostring(buffId)];
            local isAdd = true;
            if not buffShow then
                logMy('@策划buffshow not found. buffId = ' .. buffId);
                isAdd = false;
            end
            local buffServerId = value["4"];
            local buffOverlay = value["5"] or 1;--buff层数(默认为1)  向后兼容协议
            local buffPoolType = value["6"]; --池类型 1血池 2护盾池
            local buffPoolMax = value["7"];
            local buffPoolCurrent = value["8"];
            if isAdd then

                local commandInfo = {};
                commandInfo.practitioners = fighterId
                commandInfo.frame = frame;
                commandInfo.action = action;
                commandInfo.type = type;
                commandInfo.fighterId = fighterId;
                if type == EnumConst.BuffType.Del then
                    --如果是移除buff 执行者应该为目标
                    commandInfo.practitioners = targetId;
                end
                commandInfo.targetId = targetId;
                commandInfo.buffId = buffId;
                commandInfo.buffServerId = buffServerId;
                commandInfo.buffPoolType = buffPoolType;
                commandInfo.buffPoolMax = buffPoolMax;
                commandInfo.buffPoolCurrent = buffPoolCurrent;
                commandInfo.buffShow = buffShow;
                commandInfo.buffOverlay = buffOverlay;
                this.addCommand(frame, commandInfo);
            end
        elseif action == EnumConst.FightActionType.ALTERNATE or action == EnumConst.FightActionType.INIT_SUMMON then
            local fighterId = value["1"];
            local modelId = value["2"];
            local maxHP = value["3"];
            local hp = value["4"];
            local maxEnergy = value["5"];
            local energy = value["6"];
            local teamIndex = value["7"];
            if teamIndex > 0 then
                teamIndex = 2;
            else
                teamIndex = 1;
            end
            local position = value["8"];
            local weaponLevel = value["9"];
            local skinId = value["10"]
            local isHero = action ~= EnumConst.FightActionType.INIT_SUMMON;
            local isAlternate = isHero;
            if skinId == nil or skinId == 0 or G.dataTable["t_skin"][tostring(skinId)].f_SkinType == 0 then
                skinId = nil
            else
                this.skinId2Fighter[fighterId] = skinId;
            end
            this.addFighter(fighterId, modelId, teamIndex, maxHP, hp, maxEnergy, energy, position, type, weaponLevel, isHero, isAlternate, skinId);
            local commandInfo = {};
            commandInfo.frame = frame;
            commandInfo.action = action;
            commandInfo.type = type;
            commandInfo.fighterId = fighterId;
            commandInfo.position = position;
            this.addCommand(frame, commandInfo);
            table.insert(this.alternate, fighterId);
            if isHero then
                local param = {};
                param.fighterId = fighterId;
                param.modelId = modelId;
                param.teamIndex = teamIndex;
                table.insert(this.helpManFightId, param);
            end
            if FightDebug then
                local x = position["1"];
                local z = position["2"];
                fightShowLog("[ALTERNATE/INIT_SUMMON]fighterId:" .. fighterId .. " modelId:" .. modelId .. " hp:" .. hp .. "/" .. maxHP .. " mp:" .. energy .. "/" .. maxEnergy .. " pos:" .. x .. "," .. z);
                this.fighterHP[fighterId] = maxHP;
            end
        elseif action == EnumConst.FightActionType.DEATH then
            local fighterId = value["1"];
            local killerId = value["2"];
            local commandInfo = {};
            commandInfo.frame = frame;
            commandInfo.action = action;
            commandInfo.type = type;
            commandInfo.fighterId = fighterId;
            commandInfo.killerId = killerId;
            local fighter = nil
            local killer = nil;
            for k, v in pairs(this.initFighterList) do
                if fighterId == v.fighterId then
                    fighter = v;
                end
                if killerId == v.fighterId then
                    killer = v;
                end
            end

            if FightMgr.fightType == EnumConst.FightTypeConst.INSTANCE and fighter.isHero then
                if this.deadFormation == nil then
                    this.deadFormation = {};
                end
                if this.deadFormation[BattlePlaybackManager.GetFightIndex()] == nil then
                    this.deadFormation[BattlePlaybackManager.GetFightIndex()] = {};
                end
                local param = {}
                param.partnerModelId = fighter.partnerModelId;
                if fighter.partnerModelId == "610" then
                    param.partnerModelId = "61";
                end
                param.teamIndex = fighter.teamIndex;
                table.insert(this.deadFormation[BattlePlaybackManager.GetFightIndex()], param);
            end
            if killer and killer.teamIndex == 1 then
                local heroCfg = G.dataTable["t_hero"][tostring(killer.modelId)]
                local isHero = true;
                if heroCfg then
                    if heroCfg.f_Type ~= 0 then
                        isHero = false;
                    end
                else
                    isHero = false;
                end
                local modelId = killer.modelId
                if killer.modelId == "610" or killer.modelId == "611" then
                    modelId = "61";
                end
                if isHero then
                    table.insert(this.myKills, modelId)
                end
            end
            this.addCommand(frame, commandInfo);
        elseif action == EnumConst.FightActionType.ADDITIONAL_STATE then
            local fighterId = value["1"];
            local additionalStateType = value["2"];
            local commandInfo = {};
            commandInfo.frame = frame;
            commandInfo.action = action;
            commandInfo.type = type;
            commandInfo.fighterId = fighterId;
            commandInfo.additionalStateType = additionalStateType;
            this.addCommand(frame, commandInfo);
        else
        end
        if frame > this.maxFrame then
            this.maxFrame = frame;
        end
    end

    this.maxFrame = this.maxFrame + 10;
    if this.fightType == EnumConst.FightTypeConst.PerformBattle then
        local performBattleInfo = {};
        performBattleInfo.frame = 1010;
        performBattleInfo.PerformBattle = true;
        performBattleInfo.action = EnumConst.FightActionType.BUFF;
        this.addCommand(1010, performBattleInfo);

        local commentInfo1 = {}
        commentInfo1.frame = 1010;
        commentInfo1.practitioners = 9
        commentInfo1.action = EnumConst.FightActionType.BUFF;
        commentInfo1.type = EnumConst.BuffType.Del;
        commentInfo1.fighterId = 9;
        commentInfo1.targetId = 9;
        commentInfo1.buffId = 70215405;
        commentInfo1.buffServerId = 426;
        commentInfo1.buffPoolType = 0;
        commentInfo1.buffShow = G.dataTable["t_buffshow"]["70215405"];
        commentInfo1.buffOverlay = 1;
        this.addCommand(1010, commentInfo1);

        local commentInfoAdd = {}
        commentInfoAdd.frame = 1043;
        commentInfoAdd.action = EnumConst.FightActionType.ATTACK;
        commentInfoAdd.type = 0
        commentInfoAdd.fighterId = 9
        commentInfoAdd.targetId = 1
        commentInfoAdd.skillId = 552400
        commentInfoAdd.skillShow = G.dataTable["t_skillshow"][tostring(552400)];
        commentInfoAdd.attackSpeed = 1.0
        commentInfoAdd.skillFixedPos = {}
        commentInfoAdd.skillFixedPos.x = 312.0389999916554
        commentInfoAdd.skillFixedPos.y = 296.20001220703125
        commentInfoAdd.skillOnlyId = 9999
        this.addCommand(1043, commentInfoAdd);

        local commentInfo = {}
        commentInfo.frame = 1108;
        commentInfo.practitioners = 9
        commentInfo.action = EnumConst.FightActionType.BUFF;
        commentInfo.type = EnumConst.BuffType.Add;
        commentInfo.fighterId = 9;
        commentInfo.targetId = 9;
        commentInfo.buffId = 552402;
        commentInfo.buffPoolType = 0;
        commentInfo.buffShow = G.dataTable["t_buffshow"]["552402"];
        commentInfo.buffOverlay = 1;
        commentInfo.isFade = true;
        this.addCommand(1108, commentInfo);
        local endCommandInfo = {};
        endCommandInfo.frame = 1144;
        endCommandInfo.action = EnumConst.FightActionType.END;
        endCommandInfo.fighterId = 9999;
        endCommandInfo.PerformBattle = true;

        this.addCommand(1144, endCommandInfo);
        this.maxFrame = 1563;
    else
        local commandInfo = {};
        commandInfo.frame = this.frame;
        commandInfo.action = EnumConst.FightActionType.END;
        commandInfo.fighterId = 9999;
        this.addCommand(this.maxFrame, commandInfo);
    end

    if this.FightDebug then
        for i = 1, this.maxFrame do
            local commandInfos = this.commandList[i];
            if commandInfos ~= nil then
                for k, v in pairs(commandInfos) do
                    for j = 1, #v do
                        local commandInfo = v[j];
                        local fighterId = commandInfo.fighterId;
                        local targetId = commandInfo.targetId;
                        local position = commandInfo.position or {};
                        local frame = i;
                        if commandInfo.action == EnumConst.FightActionType.MOVE then
                            fightShowLog("[MOVE]frame:" .. frame .. " fighterId:" .. fighterId .. " pos:" .. tostring(position["x"]) .. "," .. tostring(position["y"]));
                        end
                    end
                end
            end
        end

        for i = 1, #this.testDamage do
            local fighterId = this.testDamage[i].fighterId;
            local targetId = this.testDamage[i].targetId;
            local type = this.testDamage[i].type;
            local damage = this.testDamage[i].damage;
            local damageType = this.testDamage[i].damageType;
            local frame = this.testDamage[i].frame;
            local skillId = this.testDamage[i].skillId;
            local skillFrame = this.testDamage[i].skillFrame;
            fightShowLog("[DAMAGE]frame:" .. frame .. " skillFrame:" .. skillFrame .. " fighterId:" .. fighterId .. " targetId:" .. targetId .. " skillId:" .. skillId .. " type:" .. damageType .. " damage:" .. damage);
        end

        for i = 1, this.maxFrame do
            local commandInfos = this.commandList[i];
            if commandInfos ~= nil then
                for k, v in pairs(commandInfos) do
                    for j = 1, #v do
                        local commandInfo = v[j];
                        local fighterId = commandInfo.fighterId;
                        local targetId = commandInfo.targetId;
                        local damage = commandInfo.damage;
                        local damageType = toNumber(commandInfo.damageType);
                        local skillId = toNumber(commandInfo.skillId);
                        local frame = i;
                        if commandInfo.action == EnumConst.FightActionType.DAMAGE then
                            fightShowLog("[REAL]frame:" .. frame .. " fighterId:" .. fighterId .. " targetId:" .. targetId .. " skillId:" .. skillId .. " type:" .. damageType .. " damage:" .. damage);
                        end
                    end
                end
            end
        end

        for i = 1, this.maxFrame do
            local commandInfos = this.commandList[i];
            if commandInfos ~= nil then
                for k, v in pairs(commandInfos) do
                    for j = 1, #v do
                        local commandInfo = v[j];
                        local fighterId = commandInfo.fighterId;
                        local targetId = commandInfo.targetId;
                        local buffId = toNumber(commandInfo.buffId);
                        local frame = i;
                        if commandInfo.action == EnumConst.FightActionType.BUFF then
                            fightShowLog("[BUFF]frame:" .. frame .. " fighterId:" .. fighterId .. " targetId:" .. targetId .. " buffId:" .. buffId);
                        end
                    end
                end
            end
        end

        for i = 1, this.maxFrame do
            local commandInfos = this.commandList[i];
            if commandInfos ~= nil then
                for k, v in pairs(commandInfos) do
                    for j = 1, #v do
                        local commandInfo = v[j];
                        local fighterId = commandInfo.fighterId;
                        local targetId = commandInfo.targetId;
                        local skillId = toNumber(commandInfo.skillId);
                        local frame = i;
                        if commandInfo.action == EnumConst.FightActionType.ATTACK then
                            fightShowLog("[ATTACK]frame:" .. frame .. " fighterId:" .. fighterId .. " targetId:" .. targetId .. " skillId:" .. skillId);
                        end
                        if commandInfo.action == EnumConst.FightActionType.HIT then
                            fightShowLog("[HIT]frame:" .. frame .. " fighterId:" .. fighterId .. " targetId:" .. targetId .. " skillId:" .. skillId);
                        end
                        if commandInfo.action == EnumConst.FightActionType.FLY or action == EnumConst.FightActionType.SKILL_PLAY then
                            fightShowLog("[FLY]frame:" .. frame .. " fighterId:" .. fighterId .. " targetId:" .. targetId .. " skillId:" .. skillId);
                        end
                    end
                end
            end
        end

        for i = 1, this.maxFrame do
            local commandInfos = this.commandList[i];
            if commandInfos ~= nil then
                for k, v in pairs(commandInfos) do
                    for j = 1, #v do
                        local commandInfo = v[j];
                        local fighterId = commandInfo.fighterId;
                        local frame = i;
                        if commandInfo.action == EnumConst.FightActionType.DEATH then
                            fightShowLog("[DEATH]frame:" .. frame .. " fighterId:" .. fighterId);
                        end
                    end
                end
            end
        end

        for k, v in pairs(this.initFighterList) do
            if this.fighterDamage[k] ~= nil and this.fighterHP[k] ~= nil then
                fightShowLog("[BEGIN]fighterId:" .. k .. " HP:" .. this.fighterHP[k] .. " Damage:" .. this.fighterDamage[k]);
            else
                fightShowLog("[BEGIN]fighterId:" .. k .. " HP:0" .. " Damage:0");
            end
        end
    end
end

function FightMgr.addPosition(frame, commandInfo)

    local onlyId = commandInfo.skillOnlyId;
    if onlyId ~= nil and onlyId ~= 0 then
        this.skillPositionList[onlyId] = commandInfo.skillFixedPos;
    end
end

function FightMgr.addCommand(frame, commandInfo)

    this.commandList[frame] = this.commandList[frame] or {};
    table.insert(this.commandList[frame], commandInfo);
end

--获取击杀敌人的英雄modelId
function FightMgr.getKillModelId()
    if this.myKills == nil then
        return {};
    end
    return this.myKills;
end

function FightMgr.doCommand(commandInfo)
    if commandInfo == nil then
        return ;
    end
    local isBattleMgr = HeroManager.GetRoleId() == "";
    local action = commandInfo.action;
    local type = commandInfo.type;
    local fighterId = commandInfo.fighterId;
    local targetId = commandInfo.targetId;
    if action == EnumConst.FightActionType.INIT then
        local x = commandInfo.position["1"];
        local z = commandInfo.position["2"];
        local fighter = this.fighterMap[fighterId];
        if fighter ~= nil then
            fighter:init();
            fighter:setPosition(Vector3(x, 300, z));
            fighter:setActive(true);
            if isBattleMgr and not fighter.isEmpty then
                if fighter.battleInfoStr == nil then
                    if fighter.name == nil then
                        fighter.name = "空"
                    end
                    fighter.battleInfoStr = "[" .. commandInfo.frame .. "]" .. "初始化英雄:" .. fighter.name .. " " .. fighterId .. " \n";
                else
                    fighter.battleInfoStr = fighter.battleInfoStr .. "[" .. commandInfo.frame .. "]" .. "初始化英雄:" .. fighter.name .. " " .. fighterId .. " \n";

                end
            end
        end
    elseif action == EnumConst.FightActionType.MOVE then
        local fighter = this.fighterMap[fighterId];
        if fighter ~= nil and commandInfo.position ~= nil then
            local x = commandInfo.position["x"];
            local z = commandInfo.position["y"];
            fighter:setWalkPos(Vector3(x, 300, z));
            if isBattleMgr then
                fighter.battleInfoStr = fighter.battleInfoStr .. "[" .. commandInfo.frame .. "]" .. fighter.name .. " " .. fighterId .. " 英雄移动到" .. "x:" .. x .. "   y:" .. z .. " \n";
            end
        end

    elseif action == EnumConst.FightActionType.CHANGE_POINT then
        local fighter = this.fighterMap[fighterId];
        if fighter ~= nil and commandInfo.position ~= nil then
            local x = commandInfo.position["x"];
            local z = commandInfo.position["y"];

            local nowPos = fighter:getWorldPosition();
            --Util.LogError('CHANGE_POINT, doCommand fighterId=' .. fighterId .. ',  x=' .. x .. ',  z=' .. z .. ',  dx=' .. (x - nowPos.x) .. ',  dz=' .. (z - nowPos.z));
            if commandInfo.subType == 2 then
                fighter.roleObj.transform:DOMove(Vector3(x, 300, z), 0.23, false):OnComplete(function()
                    if not fighter.isHook then
                        fighter:showAfterimgeSequence(nowPos, Vector3(x, 300, z));
                    end

                    --方向
                    local target = this.fighterMap[targetId];
                    if target then
                        local flip = getRoleFlip(fighter, target);
                        fighter:setFlip(flip);
                        --logMy('fighter:setFlip.', flip, fighter.roleObj.name);
                        --else
                        --    logMy('target not found.', targetId);

                        fighter:setSkillEffectFlip(EnumConst.EntitySkillEffectType.SKILLF, flip);
                        --if fighter.skillFObj ~= nil then
                        --    fighter.skillFObj:setFlip(flip);
                        --end
                    end
                end);

            elseif commandInfo.subType == 1 then
                local startPosi = fighter.roleObj.transform.position
                local endPosi = Vector3(x, 300, z)
                local tFrameTime = (commandInfo.finishFrame - commandInfo.frame) * 0.01
                local value = {};
                local time = tFrameTime;
                value.hitShowDuration = time / EnumConst.TEN_THOUSANDTH; --0.5
                value.maxHitShowDuration = value.hitShowDuration;
                Util.FlyParabola3D(fighter.roleObj, startPosi, endPosi, commandInfo.high, tFrameTime)
                --方向
                local target = this.fighterMap[targetId];
                fighter:setHitShowType(showType, value);
                fighter:setAniState(Config.AnimationState.HITFLY, nil, false, true);

                for k, list in pairs(fighter.skillEffect) do
                    for _, effect in pairs(list) do
                        if effect then
                            effect:stop(true, true);
                        end
                    end
                end

                if target then
                    local flip = getRoleFlip(fighter, target);
                    fighter:setFlip(flip);
                    --logMy('fighter:setFlip.', flip, fighter.roleObj.name);
                    --else
                    --    logMy('target not found.', targetId);

                    fighter:setSkillEffectFlip(EnumConst.EntitySkillEffectType.SKILLF, flip);
                    --if fighter.skillFObj ~= nil then
                    --    fighter.skillFObj:setFlip(flip);
                    --end
                end
            else
                fighter:setPosition(Vector3(x, 300, z));--闪现
                if not fighter.isHook then
                    fighter:showAfterimgeSequence(nowPos, Vector3(x, 300, z));
                end

                --方向
                local target = this.fighterMap[targetId];
                if target then
                    local flip = getRoleFlip(fighter, target);
                    fighter:setFlip(flip);
                    --logMy('fighter:setFlip.', flip, fighter.roleObj.name);
                    --else
                    --    logMy('target not found.', targetId);

                    fighter:setSkillEffectFlip(EnumConst.EntitySkillEffectType.SKILLF, flip);
                    --if fighter.skillFObj ~= nil then
                    --    fighter.skillFObj:setFlip(flip);
                    --end
                end
            end
            if isBattleMgr then
                fighter.battleInfoStr = fighter.battleInfoStr .. "[" .. commandInfo.frame .. "]" .. fighter.name .. " " .. fighterId .. " 英雄闪现到" .. "x:" .. x .. "   y:" .. z .. " \n";
            end
        end

    elseif action == EnumConst.FightActionType.SUPSKILLSHOW then
        FireEvent(Config.EventType.Fight_SupSkill_ui);

    elseif action == EnumConst.FightActionType.ATTACK then
        local targetId = commandInfo.targetId;
        local skillId = commandInfo.skillId;
        local skillShow = commandInfo.skillShow;
        local attackSpeed = commandInfo.attackSpeed or 1;
        local sprintEndTime = commandInfo.attackSpeed;
        local skillFixedPos = commandInfo.skillFixedPos;
        local target = this.fighterMap[targetId];
        local fighter = this.fighterMap[fighterId];
        local skillData = G.dataTable["t_skill"][tostring(skillId)];
        if skillId == nil then
            printError("技能id为空");
            return
        end
        if not skillData then
            logMy('@策划 skill not found. skillId = ' .. skillId);
            return
        end
        if skillId == 552400 then
            local a = 1;
        end
        if tonumber(skillData.f_AreaTarget) == 8 then
            --使用伤害定位
            skillFixedPos = this.skillPositionList[commandInfo.skillOnlyId];
        end
        if fighter ~= nil and target ~= nil then
            if skillData and skillData.f_UseSP == 1000 then
                --释放终结技表现
                fighter:showEnergyEff(skillData.f_SkillID);
            end
            if commandInfo.actionPos == nil then
                fighter.timeScale = attackSpeed;
            end
            this.doAttack(fighter, target, skillData, skillShow, 1, skillFixedPos, commandInfo.actionPos, commandInfo.skillOnlyId, sprintEndTime);

        end

        if isBattleMgr then
            local str = "[" .. commandInfo.frame .. "]" .. fighter.name .. " " .. fighterId .. " 对" .. target.name .. " " .. targetId .. " " .. "开始使用技能" .. skillId .. " \n";
            fighter.battleInfoStr = fighter.battleInfoStr .. str;
            target.battleInfoStr = target.battleInfoStr .. str;
        end
    elseif action == EnumConst.FightActionType.FLY then
        local targetId = commandInfo.targetId;
        local skillId = commandInfo.skillId;
        local skillShow = commandInfo.skillShow;
        local skillFixedPos = commandInfo.skillFixedPos;
        local endTime = commandInfo.endTime;
        local target = this.fighterMap[targetId];
        local fighter = this.fighterMap[fighterId];
        local skillData = G.dataTable["t_skill"][tostring(skillId)];
        if skillId == nil then
            printError("技能id为空");
            return
        end
        if not skillData then
            logMy('@策划 skill not found. skillId = ' .. skillId);
            return
        end
        if skillData and tonumber(skillData.f_AreaTarget) == 8 then
            --使用伤害定位
            skillFixedPos = this.skillPositionList[commandInfo.skillOnlyId];
        end
        if fighter ~= nil and target ~= nil then
            this.doFly(fighter, target, skillData, skillShow, skillFixedPos, commandInfo);
        end

        if isBattleMgr then
            local str = "[" .. commandInfo.frame .. "]" .. fighter.name .. " " .. fighterId .. " 对" .. target.name .. " " .. targetId .. " " .. "开始使用技能" .. skillId .. " \n";
            fighter.battleInfoStr = fighter.battleInfoStr .. str;
            target.battleInfoStr = target.battleInfoStr .. str;
        end
    elseif action == EnumConst.FightActionType.BUFF then
        local targetId = commandInfo.targetId;
        local buffId = commandInfo.buffId;
        local buffShow = commandInfo.buffShow;
        local buffServerId = commandInfo.buffServerId;
        local buffOverlay = commandInfo.buffOverlay;
        local buffPoolType = commandInfo.buffPoolType;
        local buffPoolMax = commandInfo.buffPoolMax;
        local buffPoolCurrent = commandInfo.buffPoolCurrent;

        local target = this.fighterMap[targetId];
        local fighter = this.fighterMap[fighterId];
        if commandInfo.isFade then
            for i = 1, #this.fighterList do
                local _fighter = this.fighterList[i];
                if _fighter.teamIndex == 2 then
                    _fighter:setFadeTime(0.3);
                end
            end
        end
        if commandInfo.PerformBattle then
            --表演战斗
            if this.fightType == EnumConst.FightTypeConst.PerformBattle then

                ubattletimer.delayCall(function()
                    logicMgr.StoryMgr.ShowStoryById(5001012, EnumConst.StoryShowType.review, logicMgr.StoryMgr.callback)
                    Time.timeScale = 0;

                end, 330)

            end
            return ;
        end

        if fighter ~= nil and target ~= nil then
            if buffShow == nil then
                printError("buffShow 为空 id:" .. buffId);
                return ;
            end
            local buffData = G.dataTable["t_buff"][tostring(buffId)];
            if buffData == nil then
                printError("buffId is not exist :", buffId)
                return ;
            end
            if buffId == 345401 then
                logError('doBuff 2' .. buffId);
            end
            this.doBuff(fighter, target, type, buffData, buffShow, buffServerId, buffOverlay, buffPoolType, buffPoolMax, buffPoolCurrent);

            if isBattleMgr then
                local typeStr = "添加";
                if type == EnumConst.BuffType.Del then
                    typeStr = "移除"
                elseif type == EnumConst.BuffType.ChangeOverlay then
                    typeStr = "改变层数"
                elseif type == EnumConst.BuffType.ChangePool then
                    typeStr = "改变护盾池    最大值：" .. buffPoolMax .. "   当前值：" .. buffPoolCurrent;
                end
                local str = "[" .. commandInfo.frame .. "]" .. fighter.name .. " " .. fighterId .. " 对" .. target.name .. " " .. targetId .. " " .. typeStr .. "buff    " .. "buffId:" .. buffId .. " \n";
                if fighter.battleInfoStr then
                    fighter.battleInfoStr = fighter.battleInfoStr .. str;
                else
                    fighter.battleInfoStr = str;
                end
                if target.battleInfoStr then
                    target.battleInfoStr = target.battleInfoStr .. str;
                else
                    target.battleInfoStr = str;
                end
            end
        end
        --elseif action == EnumConst.FightActionType.DAMAGE or action == EnumConst.FightActionType.REAL then


    elseif action == EnumConst.FightActionType.DAMAGE then
        local fighterId = commandInfo.fighterId;
        local targetId = commandInfo.targetId;
        local type = commandInfo.type;
        local damage = commandInfo.damage;
        local damageType = commandInfo.damageType;
        local skillInfo = commandInfo.skillInfo;
        local fighter = this.fighterMap[fighterId];
        local target = this.fighterMap[targetId];
        if this.commandDamageList[targetId] and this.commandDamageList[targetId][this.frame] then
            for i, v in pairs(this.commandDamageList[targetId][this.frame]) do
                if v.skillOnlyId == commandInfo.skillOnlyId then
                    this.commandDamageList[targetId][this.frame][i].used = true;
                end
            end
        end
        if damageType == Config.damageType.normal
                or damageType == Config.damageType.crit
                or damageType == Config.damageType.dodge
                or damageType == Config.damageType.heal
                or damageType == Config.damageType.immunity
                or damageType == Config.damageType.shields then
            if target ~= nil then
                target:damage(damageType, damage, true);
            end
        elseif damageType == Config.damageType.sp then
            if fighter ~= nil then
                if damage == 200 then
                    fighter:damage(damageType, damage, true);
                else
                    fighter:damage(damageType, damage, false);
                end
            else
                print("error: fighter is nil id:", fighterId)
            end
        end
        if damageType == Config.damageType.normal or damageType == Config.damageType.crit then
            this.fighterEndDamage[targetId] = this.fighterEndDamage[targetId] or 0;
            this.fighterEndDamage[targetId] = this.fighterEndDamage[targetId] + damage;
        elseif damageType == Config.damageType.heal then
            this.fighterEndDamage[targetId] = this.fighterEndDamage[targetId] or 0;
            this.fighterEndDamage[targetId] = this.fighterEndDamage[targetId] - damage;
        end
        if targetId == this.targetFighterId then
            if damageType == Config.damageType.normal or damageType == Config.damageType.crit then
                this.targetDamage2 = this.targetDamage2 + damage;
            elseif damageType == Config.damageType.heal then
                this.targetDamage2 = this.targetDamage2 - damage;
            end
            fightShowLog("[Test]frame:" .. this.frame .. " targetDamage2:" .. this.targetDamage2);
        end

        if isBattleMgr then
            local damageTypeStr = "普通"
            if damageType == Config.damageType.crit then
                damageTypeStr = "暴击"
            elseif damageType == Config.damageType.heal then
                damageTypeStr = "治疗"
            elseif damageType == Config.damageType.immunity then
                damageTypeStr = "免疫"
            elseif damageType == Config.damageType.sp then
                damageTypeStr = "能量"
            elseif damageType == Config.damageType.dodge then
                damageTypeStr = "闪避"

            end
            local str = commandInfo.skillId and "使用" .. commandInfo.skillId or "";
            local str = "[" .. commandInfo.frame .. "]" .. fighter.name .. " " .. fighterId .. " 对" .. target.name .. " " .. targetId .. str .. " " .. "造成 " .. damageTypeStr .. " 伤害" .. damage .. " \n";
            fighter.battleInfoStr = fighter.battleInfoStr .. str;
            target.battleInfoStr = target.battleInfoStr .. str;
        end
    elseif action == EnumConst.FightActionType.ALTERNATE then
        local x = commandInfo.position["1"];
        local z = commandInfo.position["2"];
        local fighter = this.fighterMap[fighterId];

        -- Util.WaitForSeconds(function()
        --     if fighter ~= nil then
        --         fighter:init();
        --         fighter:setPosition(Vector3(x, 300, z));
        --         fighter:setActive(true);
        --         --支援英雄上场
        --         AudioManager.Play(3008)
        --     end
        -- end, this.alternateDelay);--为特效做了一个延迟，特效播完出现，这个会配置子弹时间，不影响其他；

        local alternateDelayNum = 1
        if fighter.teamIndex == 1 and this.fightType ~= EnumConst.FightTypeConst.GuildBoss then
            alternateDelayNum = 1.7;--替补登场延时
        end
        fighter:init()
        fighter:setPosition(Vector3(x, 300, z))
        fighter:setActive(false)
        AudioManager.Play(3008)
        local f = function()
            if not HelperFunc.IsNull(fighter) then
                FireEvent(Config.EventType.Fight_HelpMan_Show, fighter.teamIndex);  --出现替补
                fighter:setActive(true)
                --支援英雄上场
            end
        end;
        if isBattleMgr then
            fighter.battleInfoStr = "[" .. commandInfo.frame .. "]" .. fighter.name .. " " .. fighterId .. " 替补登场" .. " \n";
        end

        ubattletimer.delayCall(f, alternateDelayNum * 1000)
        --this.addDelayFuncs(f, alternateDelayNum * 1000 / FightMgr.curTimeScale, true)

    elseif action == EnumConst.FightActionType.INIT_SUMMON then
        local x = commandInfo.position["1"];
        local z = commandInfo.position["2"];
        local fighter = this.fighterMap[fighterId];
        --printError(commandInfo.frame, fighterId, x, z, "伙伴位置")
        --Util.WaitForSeconds(function ()
        --如果召唤物有出场特效，需要让后端知道，前端再做延迟；不然未实例化出来，就开始移动，会出错
        if fighter ~= nil then
            fighter:init();
            fighter:setPosition(Vector3(x, 300, z));
            fighter:setActive(true);
            fighter:setAniState(Config.AnimationState.START, "start", false, true)
            if isBattleMgr then
                local str = "[" .. commandInfo.frame .. "]" .. fighter.name .. " " .. fighterId .. " 召唤物上场" .. " \n";
                fighter.battleInfoStr = str;
            end
        end
        --end, this.alternateDelay);

        fightShowLog("[INIT_SUMMON]召唤物上场 " .. fighter.fighterId .. " pos:" .. x .. "," .. z);
    elseif action == EnumConst.FightActionType.DEATH then
        local fighterId = commandInfo.fighterId;
        local killerId = commandInfo.killerId;
        local fighter = this.fighterMap[fighterId];
        local killer = this.fighterMap[killerId];
        if fighter ~= nil then
            fighter:setDead();
            FireEvent(Config.FightEvent.ROLE_DEAD, fighter);
            FireEvent(Config.EventType.Fight_Update_BossHP);
            FireEvent(Config.EventType.Fight_Update_HeroHP);
        end
        if killer ~= nil and fighter.isHero and killer.isHero then
            if not killer.killNum then
                killer.killNum = 1;
            else
                killer.killNum = killer.killNum + 1;
            end
            local param = {};
            param.fighter = fighter;
            param.killer = killer;
            FireEvent(Config.EventType.Fight_Kill_Show, param)
            --killer:showKillEffect()
            if isBattleMgr then
                local str = "[" .. commandInfo.frame .. "]" .. fighter.name .. " " .. fighterId .. " 被" .. killer.name .. " " .. killerId .. " 击杀" .. " \n";
                fighter.battleInfoStr = fighter.battleInfoStr .. str;
                killer.battleInfoStr = killer.battleInfoStr .. str;
            end
        end

        fightShowLog("[DEAD]fighterId:" .. fighterId);
    elseif action == EnumConst.FightActionType.ADDITIONAL_STATE then
        local fighterId = commandInfo.fighterId;
        local additionalStateType = commandInfo.additionalStateType;
        local fighter = this.fighterMap[fighterId];
        if fighter ~= nil then
            fighter:setAdditionalState(additionalStateType);
        end

        if isBattleMgr then

        end
        fightShowLog("[ADDITIONAL_STATE]fighterId:" .. fighterId, additionalStateType);
    elseif action == EnumConst.FightActionType.HIT then
        local fighterId = commandInfo.fighterId;
        local targetId = commandInfo.targetId;
        local skillId = commandInfo.skillId;
        local onlyId = commandInfo.skillOnlyId;
        if skillId == nil then
            printError("技能id为空");
            return
        end
        local fighter = this.fighterMap[fighterId];
        local target = this.fighterMap[targetId];
        local skillBean = G.dataTable["t_skill"][tostring(skillId)];
        if skillBean == nil then

        end
        local skillShow = G.dataTable["t_skillshow"][tostring(skillId)];
        local weaponSkill = G.dataTable["t_armskill"][tostring(skillId)];
        if skillShow == nil and weaponSkill then
            skillShow = G.dataTable["t_skillshow"][tostring(weaponSkill["f_ArmSkillReal"])];
            if skillShow == nil then
                logMy('@策划 skillShow not found. skillId = ' .. skillId);
                return ;
            end
            skillId = weaponSkill["f_ArmSkillReal"];
        end
        if skillId % 10 ~= 0 then
            --兼容之前下段技能的做法
            local startSkillId = math.floor(skillId / 10) * 10;
            local skillInfo = G.dataTable["t_skillShow"][tostring(startSkillId)];
            if skillInfo and skillInfo.f_NextSkill and skillInfo.f_NextSkill ~= "" and skillInfo.f_NextSkill[1][1] == skillId then
                skillId = startSkillId;
            end
        end
        local hits = this.getHit(skillId, fighterId, onlyId);
        if #hits > 0 then
            for i = 1, #hits do
                local hitInfo = hits[i];
                local _targetId = hitInfo.targetId;
                local _target = this.fighterMap[_targetId];
                if fighter ~= nil and _target ~= nil then
                    this.doHit(fighter, _target, skillBean, skillShow);
                end
            end
        else
            if target ~= nil then
                this.doHit(fighter, target, skillBean, skillShow);
            end
        end
        if isBattleMgr then

        end
    elseif action == EnumConst.FightActionType.END then
        --三秒延迟
        if commandInfo.PerformBattle then
            FireEvent(Config.EventType.PerformBattlePlay, true)
        else
            this.doEnd();
        end

    end


end
--检查伤害列表是否都使用过
function FightMgr.checkDamageListIsEnd()
    local isEnd = true;
    for skillId, damageInfo in pairs(this.damageDataList) do
        for fightId, info in pairs(damageInfo) do
            for k, v in pairs(info) do
                for _, m in pairs(v) do
                    if m.used == false and m.damageType ~= 0 then
                        isEnd = false;
                        --伤害堆栈没跑完
                        local fightId = (BattlePlaybackManager.getBattleRecord() and BattlePlaybackManager.getBattleRecord().fightId) and BattlePlaybackManager.getBattleRecord().fightId or 0
                        local skillId = m.skillId or 0
                        printError("伤害堆栈没跑完  技能id==", skillId, m.damage, "帧数==", m.frame);
                        --return isEnd;
                    end
                end
            end
        end
    end
    for i, v in pairs(this.damageTemp) do
        printError("人物死亡伤害未触发  技能id==", v.skillId, v.damage, "帧数==", v.frame);
    end

    return isEnd;
end

--战斗结束操作
function FightMgr.doEnd()
    local isEnd = true;
    for i = 1, #this.fighterList do
        local entity = this.fighterList[i];
        for k, list in pairs(this.fighterList[i].skillEffect) do
            for type, effect in pairs(list) do
                if effect then
                    if effect.duration and effect.duration >= 1 then
                        isEnd = false
                    end
                    effect:stop();
                    entity.skillEffect[k][type] = nil
                end
            end
            entity.skillEffect[k] = nil
        end
        if entity.roleObj and not entity.isDead then
            if entity.skeletonAnimation then
                Util.Lua_GameObjectAddPosAndSetRot(entity.skeletonAnimation.gameObject, 0, 0, 0, 40, 0, 0);
            end
            entity.roleObj:SetActive(true)
            if not entity.isDeading then
                entity.aniStateNew = Config.AnimationState.IDLE;
                entity.aniState = Config.AnimationState.IDLE;
                entity.timeScale = 1;
                entity:playAction(Config.AnimationStateName.IDLE);
                entity:onUpdate(Time.deltaTime);
            else
                entity.stopFrame = 0;
                entity.stopDuration = 0;
                entity.timeScale = 1;
                if not Util.IsNull(entity.skeletonAnimation) and not Util.IsNull(entity.shadow.skeletonAnimation) then
                    Util.SetActionTimeScale(entity.skeletonAnimation, entity.skeletonAnimation.AnimationName, 1);
                    Util.SetActionTimeScale(entity.shadow.skeletonAnimation, entity.shadow.skeletonAnimation.AnimationName, 1);

                end
                --entity.timeScale = 1;
            end
            --printError("名字--",self.name,"新状态",self.aniStateNew,"当前状态",self.aniState);
            if entity.skeletonAnimation and entity.skeletonAnimation.Skeleton.A ~= 1 then
                entity.skeletonAnimation.Skeleton.A = 1
            end
            if entity.shadow and entity.shadow.skeletonAnimation and entity.shadow.skeletonAnimation.Skeleton.A ~= 1 then
                entity.shadow.skeletonAnimation.Skeleton.A = 1
            end
        end
    end
    this.gameEnd = true
    isEnd = isEnd and FightMgr.checkDamageListIsEnd() or false
    if not isEnd then
        --this.addDelayFuncs(this.endAction, this.endTime / FightMgr.curTimeScale, true)
        this.endTimer = ubattletimer.timeCall(this.endAction, this.endTime)
        return ;
    end
    if isEnd then
        this.endAction()
    end
end

function FightMgr.endAction()
    local battle_round_transform = panelMgr.BattleRound.transform
    for i = 0, battle_round_transform.childCount - 1 do
        local Obj = battle_round_transform:GetChild(i).gameObject
        if string.Contains(Obj.name, 'fx') then
            Obj:SetActive(false)
        end
    end

    if this.endTimer then
        ubattletimer.remove(this.endTimer);
    end

    for k, v in pairs(this.fighterMap) do
        if this.fighterHP[k] ~= nil and this.fighterEndDamage[k] ~= nil then
            fightShowLog("[END]fighterId:" .. k .. " HP:" .. this.fighterHP[k] .. " Damage:" .. this.fighterEndDamage[k]);
        else
            fightShowLog("[END]fighterId:" .. k .. " HP:0" .. " Damage:0");
        end
    end

    for i = 1, #this.testDamage do
        if this.testDamage[i].used == nil or this.testDamage[i].used == false then
            fightShowLog("[DAMAGE]没有匹配到的伤害 frame:" .. this.testDamage[i].frame .. " SkillID:" .. this.testDamage[i].skillId .. " Damage:" .. this.testDamage[i].damage .. " Type:" .. this.testDamage[i].damageType);
        end
    end
    this.endCommand();
end

function FightMgr.beginCommand()
    if not this.hasInit then
        return
    end
    this.gameEnd = false
    if not this.handle then
        this.starTime = 0;
        this.lastTime = 0;
        this.frame = 0;
        this.handle = UpdateBeat:Add(this.update, this);
    end
    TAManager.TrackByDictionary("fight_begin")
end

function FightMgr.stopCommand()

    if this.handle then
        UpdateBeat:Remove(this.update, this);
        this.handle = nil;
    end
    if this.entranceHandle then
        UpdateBeat:Remove(this.onUpdateEntrance, this);
        this.entranceHandle = nil
    end
end

function FightMgr.updateFrame(frame)

    if this.commandList == nil or this.commandList[frame] == nil then
        return ;
    end
    fightShowLog("[UPDATE]Frame:" .. frame);
    if this.showFrame then
        printError("[UPDATE]Frame==:" .. frame);
    end
    local frameCommand = this.commandList[frame];
    local cutinCom = false
    if frameCommand ~= nil then
        for i = 1, #frameCommand do
            local commandInfo = frameCommand[i];

            if cutinCom then
                --logMy("插入黑屏指令",frame,commandInfo)
                table.insert(this.cutInCmdList, commandInfo);
            else
                --logMy("执行指令",frame,commandInfo)

                local helpId = 0;
                for i, v in pairs(FightMgr.helpManFightId) do
                    if v.teamIndex == 1 then
                        helpId = v.fighterId;
                    end
                end
                if (commandInfo.skillId and commandInfo.skillId == 103) then
                    --logMy("黑屏指令")
                    cutinCom = true
                end
                this.doCommand(commandInfo);
            end
        end
    end
end

function FightMgr.updateFrameCutIn(deltaTime)
    this.cutInTime = this.cutInTime - deltaTime;
    if this.cutInSkillTime ~= 0 then
        this.cutInSkillTime = this.cutInSkillTime - deltaTime;
    end
    if this.cutInTime < 0 then
        this.cutInState = false;
        this.supSkillCutIn = false;
        this.isSkillCutIn = false;
        this.curTimeScale = this.supSkillTempTime;
        Time.timeScale = this.curTimeScale;
        --log("================this.cutInState = false"..this.starTime)
        for i = 1, #this.fighterList do
            local _fighter = this.fighterList[i];
            _fighter:ResumeCurrentAction();
            _fighter:ResumeEffect();
            _fighter:setOrder(Config.SortingDefault.Role);
            _fighter:stopFullScreen();
            _fighter.cutInTime = 0;
        end
        for i = 1, #this.effectTempCacheList do
            if this.effectTempCacheList[i] then
                this.effectTempCacheList[i]:play();
            end
        end
        if #this.cutInCmdList > 0 then
            for i = 1, #this.cutInCmdList do
                local cmd = this.cutInCmdList[i];
                this.doCommand(cmd);
            end
        end
        this.cutInCmdList = {};
        --log("ClientFightManager.updateFrameCutIn3");
        return ;
    else
        for i = 1, #this.fighterList do
            local _fighter = this.fighterList[i];
            if _fighter.cutInTime > 0 then
                _fighter.cutInTime = _fighter.cutInTime - deltaTime;
                if _fighter.cutInTime <= 0 then
                    _fighter.cutInTime = 0;
                    _fighter:PauseCurrentAction();
                    _fighter:PauseEffect();
                end
            end
        end

    end
    --ClientFight.FightClientManager.cutInFrame(ClientFight.FightClientManager.fight)

    if this.cutInSkillTime < 0 and #this.cutInCmdList > 0 then
        local cmd = this.cutInCmdList[1];
        this.doCommand(cmd);
        table.remove(this.cutInCmdList, 1);
    end
end

function FightMgr.addFighter(fighterId, modelId, teamIndex, maxHP, hp, maxEnergy, energy, position, type, weaponLevel, isHero, isAlternate, skinId)
    local fighterInfo = {};
    fighterInfo.fighterId = fighterId;
    fighterInfo.partnerModelId = modelId;
    fighterInfo.modelId = modelId;
    fighterInfo.isEmpty = type == 1;--没有模型的GameObject对象,FightActionType.INIT,type==1，
    if (not fighterInfo.isEmpty) then
        logicMgr.HeroManager.copyHeroConfigbyModelId(fighterInfo.partnerModelId, fighterInfo)
    end
    fighterInfo.maxHP = maxHP;
    fighterInfo.hp = hp;
    fighterInfo.maxEnergy = maxEnergy;
    fighterInfo.energy = energy;
    fighterInfo.teamIndex = teamIndex;
    fighterInfo.position = Vector2(position["1"], position["2"]);
    fighterInfo.weaponLevel = weaponLevel;
    fighterInfo.isHero = isHero;
    fighterInfo.isAlternate = isAlternate;--是否是替补
    fighterInfo.skinId = skinId;
    table.insert(this.initFighterList, fighterInfo);
    if (not fighterInfo.isEmpty) then
        this.addModelRes(fighterInfo.partnerModelId, fighterInfo.skinId);
    end
end

function FightMgr.createFighter(fightInfo, call)
    local battleRoundRoot = panelMgr.BattleRound;
    local heroCfg = G.dataTable["t_hero"][tostring(fightInfo.partnerModelId)];
    local isBloodBar = true;
    if not heroCfg or (heroCfg and tonumber(heroCfg.f_LifeBar) == 1) then
        isBloodBar = false;
    end
    local roleFighter = FightEntity:new(fightInfo, isBloodBar);

    roleFighter:initAvatar(battleRoundRoot.transform, function()
        if fightInfo.position ~= nil then
            roleFighter:setPosition(Vector3(fightInfo.position.x, 300, fightInfo.position.y));
        else
            roleFighter:setPosition(Vector3(297, 300, 279));
        end
        if call then
            call(roleFighter)
        end
    end);
    return roleFighter;
end
function FightMgr.createPet(petInfo, call)

    if FightMgr.fightType == EnumConst.FightTypeConst.RankBattle then
        return ;
    end
    local battleRoundRoot = panelMgr.BattleRound;
    local pet = PetEntity:New();
    pet.teamIndex = petInfo.teamIndex;
    pet.petId = petInfo.petId;
    pet.camp = petInfo.camp;

    pet:createPet(battleRoundRoot.transform, function()
        if petInfo.position ~= nil then
            pet:setPosition(Vector3(petInfo.position.x, 300, petInfo.position.y));
        else
            pet:setPosition(Vector3(297, 300, 279));
        end
        if call then
            call(pet)
        end
    end);
    return pet;
end

function FightMgr.addSkill(skillId, skillShow)

    if indexofTable(this.initSkillList, skillId) > 0 then
        return ;
    end
    table.insert(this.initSkillList, skillId);

    if skillShow ~= nil then
        local skinId = this.skinId2Fighter[fighterId];
        if logicMgr.SkillManager.checkSkillSkin(skillId) then
            --大招释放表现通用 不因为皮肤改变而改变
            skinId = nil;
        end
        local preeffectList = skillShow.f_SkillFResource;
        --local preeffectList = string.split(preeffectRaw,",");
        local preeffect = preeffectList[1];

        local path = "Prefabs/Skill/"

        if preeffect ~= nil and preeffect ~= "" then
            if skinId then
                preeffect = preeffect .. "-" .. skinId;
            end
            this.resList[path .. preeffect] = "Effect"
        end

        if #preeffectList > 1 then
            preeffect = preeffectList[2];
            if preeffect ~= nil and preeffect ~= "" then
                if skinId then
                    preeffect = preeffect .. "-" .. skinId;
                end
                this.resList[path .. preeffect] = "Effect"
            end
        end

        local preeffect_b = skillShow.f_SkillBResource;
        if preeffect_b ~= nil and preeffect_b ~= "" then
            if skinId then
                preeffect_b = preeffect_b .. "-" .. skinId;
            end
            this.resList[path .. preeffect_b] = "Effect"
        end
        local flyeffect = skillShow.f_FlyFResource;
        if flyeffect ~= nil and flyeffect ~= "" then
            if skinId then
                flyeffect = flyeffect .. "-" .. skinId;
            end
            this.resList[path .. flyeffect] = "Effect"
        end
        local flyeffect_b = skillShow.f_FlyBResource;
        if flyeffect_b ~= nil and flyeffect_b ~= "" then
            if skinId then
                flyeffect_b = flyeffect_b .. "-" .. skinId;
            end
            this.resList[path .. flyeffect_b] = "Effect"
        end
        local hiteffect = skillShow.f_HitFResource;
        if hiteffect ~= nil and hiteffect ~= "" then
            if skinId then
                hiteffect = hiteffect .. "-" .. skinId;
            end
            this.resList[path .. hiteffect] = "Effect"
        end
        local hiteffect_b = skillShow.f_HitBResource;
        if hiteffect_b ~= nil and hiteffect_b ~= "" then
            if skinId then
                hiteffect_b = hiteffect_b .. "-" .. skinId;
            end
            this.resList[path .. hiteffect_b] = "Effect"
        end
        local sceneEffect = skillShow.f_HitBResource;
        if hiteffect_b ~= nil and hiteffect_b ~= "" then
            if skinId then
                hiteffect_b = hiteffect_b .. "-" .. skinId;
            end
            this.resList[path .. hiteffect_b] = "Effect"
        end
    end

end

function FightMgr.addHit(frame, hitInfo)

    local skillId = hitInfo.skillId;
    local weaponSkill = G.dataTable["t_armskill"][tostring(skillId)];
    local skillCfg = G.dataTable["t_skillshow"][tostring(skillId)]
    if weaponSkill and skillCfg == nil then
        skillId = weaponSkill["f_ArmSkillReal"];
        skillCfg = G.dataTable["t_skillshow"][tostring(skillId)]
    end
    if skillCfg.f_HurtSource ~= 0 then
        skillId = skillCfg.f_HurtSource;
    end
    local fighterId = hitInfo.fighterId;
    hitInfo.used = false;
    if skillId ~= nil and skillId > 0 and fighterId ~= nil and fighterId > 0 then
        this.hitDataList[skillId] = this.hitDataList[skillId] or {};
        this.hitDataList[skillId][fighterId] = this.hitDataList[skillId][fighterId] or {};
        table.insert(this.hitDataList[skillId][fighterId], hitInfo);
    end
end

function FightMgr.getHit(skillId, fighterId, onlyId)

    local list = {};
    if this.hitDataList[skillId] ~= nil then
        local hits = this.hitDataList[skillId][fighterId];
        if hits ~= nil and #hits > 0 then
            for i = 1, #hits do
                if hits[i].skillOnlyId == onlyId and hits[i].used == false then
                    this.hitDataList[skillId][fighterId][i].used = true;
                    table.insert(list, hits[i]);
                end
            end
        end
    end
    return list;
end

function FightMgr.addDamage(frame, damageInfo)
    local skillId = damageInfo.skillId;
    local fighterId = damageInfo.fighterId;
    if skillId ~= nil and skillId > 0 and fighterId ~= nil and fighterId > 0 then
        this.damageDataList[skillId] = this.damageDataList[skillId] or {};
        this.damageDataList[skillId][fighterId] = this.damageDataList[skillId][fighterId] or {};
        this.damageDataList[skillId][fighterId][frame] = this.damageDataList[skillId][fighterId][frame] or {};
        table.insert(this.damageDataList[skillId][fighterId][frame], damageInfo);
    end
end

function FightMgr.getDamage(skillId, fighterId, time, onlyId)

    if skillId < 1000 then
        return ;
    end
    if onlyId == 68 then
        local a = 1;
    end
    local list = {};
    local frame = Mathf.Floor(time * defaultFrame * this.curTimeScale);
    local skillCfg = G.dataTable["t_skillshow"][tostring(skillId)]
    if skillCfg == nil then
        logMy('@策划 skillShow not found. skillId = ' .. skillId);
        return ;
    end
    if skillCfg.f_HurtSource ~= 0 then
        ----兼容之前下段技能的做法
        --local startSkillId = math.floor(skillId / 10) * 10;
        --local skillInfo = G.dataTable["t_skillShow"][tostring(startSkillId)];
        --if skillInfo and skillInfo.f_NextSkill and skillInfo.f_NextSkill ~= "" and skillInfo.f_NextSkill[1][1] == skillId and skillCfg.f_HurtSource  then
        skillId = skillCfg.f_HurtSource;
        --end
    end
    if this.damageDataList[skillId] ~= nil then
        local damages = this.damageDataList[skillId][fighterId];
        if damages ~= nil then
            local useNum = 0;
            for i, v in pairs(damages) do
                --+10容错，防止把后边触发的伤害一次性弹出
                if this.cutInState then
                    local skillFrame = -1;
                    if v ~= nil and #v > 0 then
                        for j = 1, #v do
                            if not v[j].used and (skillFrame == -1 or skillFrame == v[j].skillFrame) and v[j].skillOnlyId == onlyId then
                                skillFrame = clone(v[j].skillFrame);
                                v[j].used = true;
                                table.insert(list, v[j]);
                            else
                            end
                        end
                    end
                    if #list > 0 then
                        return list;
                    end
                else
                    local skillFrame = -1;
                    if v ~= nil and #v > 0 then
                        for j = 1, #v do
                            if not v[j].used and (skillFrame == -1 or skillFrame == v[j].skillFrame) and v[j].skillOnlyId == onlyId then
                                skillFrame = clone(v[j].skillFrame);
                                v[j].used = true;
                                if HeroManager.GetRoleId() == "" then
                                    local fighter = this.fighterMap[fighterId];
                                    local targetId = v[j].targetId;
                                    local target = this.fighterMap[targetId];
                                    local damageTypeStr = "普通"
                                    if v[j].damageType == Config.damageType.crit then
                                        damageTypeStr = "暴击"
                                    elseif v[j].damageType == Config.damageType.heal then
                                        damageTypeStr = "治疗"
                                    elseif v[j].damageType == Config.damageType.immunity then
                                        damageTypeStr = "免疫"
                                    elseif v[j].damageType == Config.damageType.sp then
                                        damageTypeStr = "能量"
                                    elseif v[j].damageType == Config.damageType.dodge then
                                        damageTypeStr = "闪避"
                                    end
                                    local str = "[" .. v[j].frame .. "]" .. fighter.name .. " " .. fighterId .. " 对" .. target.name .. " " .. targetId .. "使用" .. skillId .. " " .. "造成 " .. damageTypeStr .. " 伤害" .. v[j].damage .. " \n";
                                    fighter.battleInfoStr = fighter.battleInfoStr .. str;
                                    target.battleInfoStr = target.battleInfoStr .. str;
                                end
                                table.insert(list, v[j]);
                            else
                            end
                        end
                    end
                    if #list > 0 then
                        return list;
                    end
                    --[[
                                        if v ~= nil and #v > 0 and not v[1].used then
                                            v[1].used = true;
                                            for j=1,#v do
                                                v[j].used = true;
                                            end
                                            concactTable(list,v);
                                            return list;
                                        end
                    ]]
                end
            end
        end
    end
    return list;
end
---@return 返回他人未使用的动画帧触发伤害
function FightMgr.getDamageAfterCurrentFrame(targetId, frame)

    --读取帧事件的伤害
    local damageList = {}
    for k, v in pairs(this.damageDataList) do
        for k1, v1 in pairs(v) do
            for k2, v2 in pairs(v1) do
                for k3, v3 in pairs(v2) do
                    if v3 then
                        if frame and frame == v3.frame then
                            table.insert(damageList, v3);
                        elseif not frame and v3.targetId == targetId and v3.used == false then
                            v3.isFrame = true;
                            table.insert(damageList, v3);
                            return v3
                        end
                    end
                end
            end
        end
    end
    --读取非帧事件的伤害
    if this.commandDamageList[targetId] and not frame then
        for k, v in pairs(this.commandDamageList[targetId]) do
            for k1, v1 in pairs(v) do
                if v1.used == false then
                    table.insert(damageList, v1);
                end
            end
        end
    end

    return table.getn(damageList) > 0 and damageList or nil;
end

---@return 返回他人未使用的动画帧触发伤害
function FightMgr.getDamageAfterOtherFrame(fighterId)
    local damageList = {}
    for k, v in pairs(this.damageDataList) do
        for k1, v1 in pairs(v) do
            for k2, v2 in pairs(v1) do
                for k3, v3 in pairs(v2) do
                    if v3 then
                        if v3.fighterId == fighterId and v3.used == false then
                            table.insert(damageList, v3);
                        end
                    end
                end
            end
        end
    end
    return damageList;
end

---@return 返回唯一id未使用的动画帧触发伤害
function FightMgr.getDamageAfterOtherOnlyId(onlyId)

    local damageList = {}
    if onlyId == nil then
        return {};
    end
    for k, v in pairs(this.damageDataList) do
        for k1, v1 in pairs(v) do
            for k2, v2 in pairs(v1) do
                for k3, v3 in pairs(v2) do
                    if v3 then
                        if v3.skillOnlyId == onlyId and v3.used == false then
                            table.insert(damageList, v3);
                        end
                    end
                end
            end
        end
    end
    return damageList;
end

function FightMgr.initFighter(finishCall)

    local totalCount = #this.initFighterList
    local loadedCount = 0
    for i = 1, #this.initFighterList do
        this.createFighter(this.initFighterList[i], function(fighter)
            loadedCount = loadedCount + 1

            table.insert(this.fighterList, fighter);
            this.fighterMap[fighter.fighterId] = fighter;
            if this.fighterMap[fighter.fighterId] == nil then
                print("fighter有问题", fighter, this.initFighterList[i].fighterId);
            end

            if loadedCount >= totalCount then
                if finishCall then
                    finishCall()
                end
            end
        end);
    end
end
function FightMgr.initPet(finishCall)
    local petInfo_1 = {};
    petInfo_1.teamIndex = 1;
    petInfo_1.petId = PetManager.CurrentPetId;
    petInfo_1.position = {};
    petInfo_1.position.x = 303;
    petInfo_1.position.y = 300;
    petInfo_1.camp = EnumConst.CampType.Attack;

    local petInfo_2 = {};
    petInfo_2.teamIndex = 2;
    petInfo_2.petId = 0;
    petInfo_2.position = {};
    petInfo_2.position.x = 312;--位置
    petInfo_2.position.y = 300;
    petInfo_2.camp = EnumConst.CampType.Defence;

    if petInfo_1.petId ~= 0 then
        this.createPet(petInfo_1, function(pet)
            this.pet_1 = pet;
            if this.pet_1 and this.pet_2 then
                if finishCall then
                    finishCall()
                end
            end
        end);
    end

    if petInfo_2.petId ~= 0 then
        this.createPet(petInfo_2, function(pet)
            this.pet_2 = pet;
            if this.pet_1 and this.pet_2 then
                if finishCall then
                    finishCall()
                end
            end
        end);
    end
end

function UserDataEventDelegate(e, userdata)
    --log("UserDataEventDelegate");
    local time = e.Time;
    local skillIdList = {}
    string_split(userdata.Name, "_", skillIdList);

    local skillId = toNumber(skillIdList[1]) or 0;
    if table.getn(skillIdList) == 0 then
        skillId = userdata.Name
    end
    local weaponSkill = G.dataTable["t_armskill"][tostring(skillId)];
    if weaponSkill then
        skillId = weaponSkill["f_ArmSkillReal"];
    end
    local onlyId = toNumber(skillIdList[2]) or 0;
    local fighterId = userdata.Int;
    local targetId = Mathf.Floor(userdata.Float);
    local skillShow = this.skeletonAnimStateUserDataString[skillId]

    if e.Int == EnumConst.SpineEventType.HIT then
        fightShowLog("[EventType.HIT]skillId:" .. skillId);
        local fighter = this.fighterMap[fighterId];
        local target = this.fighterMap[targetId];
        local skillBean = G.dataTable["t_skill"][tostring(skillId)];
        if skillShow == nil then
            skillShow = G.dataTable["t_skillshow"][tostring(skillId)];
        end

        if skillId % 10 ~= 0 then
            --兼容之前下段技能的做法
            local startSkillId = math.floor(skillId / 10) * 10;
            local skillInfo = G.dataTable["t_skillShow"][tostring(startSkillId)];
            if skillInfo and skillInfo.f_NextSkill and skillInfo.f_NextSkill ~= "" and skillInfo.f_NextSkill[1][1] == skillId then
                skillId = startSkillId;
            end
        end
        local hits = this.getHit(skillId, fighterId, onlyId);
        if #hits > 0 then
            for i = 1, #hits do
                local hitInfo = hits[i];
                local _targetId = hitInfo.targetId;
                local _target = this.fighterMap[_targetId];
                if fighter ~= nil and _target ~= nil then
                    this.doHit(fighter, _target, skillBean, skillShow);
                end
            end
        else
            --if target ~= nil then
            --    this.doHit(fighter, target, skillBean, skillShow);
            --end
        end
    elseif e.Int == EnumConst.SpineEventType.DAMAGE then
        fightShowLog("[EventType.DAMAGE]skillId:" .. skillId);

        local damages = this.getDamage(skillId, fighterId, this.gameTime + 0.0001, onlyId);
        if damages and #damages > 0 then
            for i = 1, #damages do
                local fighterId = damages[i].fighterId;
                local targetId = damages[i].targetId;
                local damage = damages[i].damage;
                local damageType = damages[i].damageType;
                local target = this.fighterMap[targetId];
                if target ~= nil then
                    target:damage(damageType, damage, true);
                else
                    print("error: damage target is nil targetId=" .. targetId)
                end
                fightShowLog("[EventType.DAMAGE]frame:" .. damages[i].frame .. " fighterId:" .. fighterId .. " targetId:" .. targetId .. " skillId:" .. skillId .. " damage:" .. damage);

                if damageType == Config.damageType.normal or damageType == Config.damageType.crit then
                    this.fighterEndDamage[targetId] = this.fighterEndDamage[targetId] or 0;
                    this.fighterEndDamage[targetId] = this.fighterEndDamage[targetId] + damage;
                elseif damageType == Config.damageType.heal then
                    this.fighterEndDamage[targetId] = this.fighterEndDamage[targetId] or 0;
                    this.fighterEndDamage[targetId] = this.fighterEndDamage[targetId] - damage;
                end

                if targetId == this.targetFighterId then
                    if damageType == Config.damageType.normal or damageType == Config.damageType.crit then
                        this.targetDamage2 = this.targetDamage2 + damage;
                    elseif damageType == Config.damageType.heal then
                        this.targetDamage2 = this.targetDamage2 - damage;
                    end
                    fightShowLog("[Test]frame:" .. this.frame .. " targetDamage2:" .. this.targetDamage2);
                end
            end
        else
            fightShowLog("[EventType.DAMAGE]不能匹配到技能伤害 fighterId:" .. fighterId .. "skillId:" .. skillId);
        end
    elseif e.Int == EnumConst.SpineEventType.CAMERA then
        local target = this.fighterMap[targetId];
        if not HelperFunc.IsNull(target) then
            target:ShakeCamera(1, 200);
        end
    end
end

function FightMgr.removeSkeletonEvent(skeleton, fighterId, targetId, skillId, skillShow)

    if skeleton ~= nil then
        local skeletonAnim = skeleton:GetComponent("SkeletonAnimation");
        if skeletonAnim ~= nil and skeletonAnim.state ~= nil then
            -- skeletonAnim.state.UserData = Spine.EventData.New(tostring(skillId));
            -- skeletonAnim.state.UserData.Int = fighterId;
            -- skeletonAnim.state.UserData.Float = targetId;
            -- skeletonAnim.state.UserData.String = "";
            skeletonAnim:SetAnimationStateEventData(tostring(skillId), tonumber(fighterId), tonumber(targetId)) --string event_name, int int_data, float float_data, string string_data = null

            this.skeletonAnimStateUserDataString[skillId] = skillShow
            -- skeletonAnim.state.UserEvent = skeletonAnim.state.UserEvent - UserDataEventDelegate;
            skeletonAnim:UnRegisterStateLuaUserFunction()

            --??
            --skeletonAnim.state.UserEvent = skeletonAnim.state.UserEvent + UserDataEventDelegate;
        end
    end
end

function FightMgr.addSkeletonEvent(skeletonAnim, fighterId, targetId, skillId, skillShow, skillOnlyId)

    --if skeletonAnim ~= nil then
    --local skeletonAnim = skeleton:GetComponent("SkeletonAnimation");
    if not Util.IsNull(skeletonAnim) and skeletonAnim.state ~= nil then
        -- skeletonAnim.state.UserData = Spine.EventData.New(tostring(skillId));
        -- skeletonAnim.state.UserData.Int = fighterId;
        -- skeletonAnim.state.UserData.Float = targetId;
        -- skeletonAnim.state.UserData.String = "";
        local skillNameData = skillId .. "_" .. skillOnlyId;
        skeletonAnim:SetAnimationStateEventData(tostring(skillNameData), tonumber(fighterId), tonumber(targetId)) --string event_name, int int_data, float float_data, string string_data = null

        this.skeletonAnimStateUserDataString[skillId] = skillShow
        -- skeletonAnim.state.UserEvent = skeletonAnim.state.UserEvent - UserDataEventDelegate;
        -- skeletonAnim.state.UserEvent = skeletonAnim.state.UserEvent + UserDataEventDelegate;
        skeletonAnim:RegisterStateLuaUserFunction(UserDataEventDelegate)
    else
        --else
        --    logMy('addSkeletonEvent skeletonAnim == nil', skeletonAnim, fighterId,targetId,skillId,skillShow);
    end
end

function FightMgr.setCamera(camera)

    cameraMain = camera;
    cameraMainControllerParam = {};
    cameraMainControllerParam.transform = cameraMain.transform;--cache

    local frameTime = EnumConst.FIGHT_FRAME * 0.001; -- time太长了
    --cameraMainControllerParam.times = {0, 8 * frameTime, 63 * frameTime, 76 * frameTime};
    cameraMainControllerParam.times = { 0, 2 * frameTime, 57 * frameTime };
    --cameraMainControllerParam.positions = {Vector3(297.5, 314, 279.5), Vector3(297.5, 314, 279.5), Vector3(307.2, 314, 279.5), Vector3(307.5, 314, 279.5)};
    cameraMainControllerParam.positions = { Vector3(297.5, 314, 279.5), Vector3(297.5, 314, 279.5), Vector3(307.5, 314, 279.5) };
    cameraMainControllerParam.time = 0;
    cameraMainControllerParam.done = false;
end

function FightMgr.getCamera()

    return cameraMain;
end

function FightMgr.addModelRes(modelId, skinId)

    local modefile = HeroManager.GetHeroDrawingRolePath(modelId, nil, skinId)
    this.resList[modefile] = "Model"
end

function FightMgr.addSkillRes(SkillId)

    local modefile = "Prefabs/Skill/" .. SkillId;
    this.resList[modefile] = "Effect"
end

--攻击
--如果技能是定点释放的skillFixedPos就是位置
function FightMgr.doAttack(fighter, target, skillData, skillShow, attackSpeed, skillFixedPos, actionPos, skillOnlyId, sprintEndTime)
    --fightShowLog("[DoAttack]fighterId:"..fighter.fighterId.."skillId:"..skillShow.f_SkillID);
    if skillShow and skillData == nil then
        print("skillData is nil, id==", skillShow.f_SkillID)
    end
    if skillShow == nil and skillData then
        print("skillShow is nil, id==", skillData.f_SkillID)
        return ;
    end
    if skillShow.f_SkillID == 682202 then
        local a = 1;
    end

    --死了还能打，造成游戏结束，部分玩家未死亡bug。
    --if fighter:getDeadState() then
    --    fighter:init();
    --    fighter:setActive(true);
    --end

    if skillData ~= nil then

        this.doSkillAttack(fighter, target, skillData, skillShow, attackSpeed, skillFixedPos, actionPos, skillOnlyId, sprintEndTime)
    else

        this.doShowAttack(fighter, target, skillShow, attackSpeed, skillFixedPos, skillOnlyId, sprintEndTime);
    end
end

function FightMgr.doSkillAttack(fighter, target, skillData, skillShow, attackSpeed, skillFixedPos, actionPos, skillOnlyId, sprintEndTime)
    --if skillShow and skillShow.f_SkillID == 90100011 then
    --    printError("0000")
    --end
    local helpId = 0;
    for i, v in pairs(FightMgr.helpManFightId) do
        if v.teamIndex == 1 then
            helpId = v.fighterId;
        end
    end
    local supBulletTime = 1200;
    local supSkillId = FightMgr.battleInfo.mySupSkill;
    if skillShow.f_SkillShowType ~= nil and skillShow.f_SkillShowType ~= "" and skillData ~= nil then

        if fighter and fighter.isEmpty then
            FireEvent(Config.EventType.Fight_HelpMan_Show_Skill, fighter.teamIndex);  --出现替补后，释放替补技能
        end
        local showType = toNumber(skillShow.f_SkillShowType);
        --local showValue = toNumber(skillShow.f_SkillShowValue);
        local showValueTbl = skillShow.f_SkillShowValue or {};
        local showValue = showValueTbl[1] or 0;
        local attackShowDuration = toNumber(skillData.f_GuideTime);
        local attackMoveSpeed = toNumber(skillData.f_Speed);
        local flip = getRoleFlip(fighter, target);
        local attackIsPos = tonumber(skillData.f_AreaTarget) == 7 or tonumber(skillData.f_AreaTarget) == 8;
        fighter:setFlip(flip);
        if skillShow.f_SkillID == supSkillId and fighter.teamIndex == 1 and this.fightType ~= EnumConst.FightTypeConst.GuildBoss then
            --支援技能暂停之后播放
            local effFObj, effBObj = nil;

            helpManShow = function()
                effFObj, effBObj = fighter:playSkill(fighter, skillShow, flip, 1, target, attackIsPos, skillFixedPos);

                --场景特效
                local effFCenterObj, effBCenterObj = fighter:playCenter(fighter, skillShow);

                if effFObj ~= nil then
                    FightMgr.addSkeletonEvent(effFObj:getSkeletonAnimation(), fighter.fighterId, target.fighterId, skillData.f_SkillID, skillShow, skillOnlyId);
                end
                if effBObj ~= nil then
                    FightMgr.addSkeletonEvent(effBObj:getSkeletonAnimation(), fighter.fighterId, target.fighterId, skillData.f_SkillID, skillShow, skillOnlyId);
                end
                if effFCenterObj ~= nil then
                    FightMgr.addSkeletonEvent(effFCenterObj:getSkeletonAnimation(), fighter.fighterId, target.fighterId, skillData.f_SkillID, skillShow, skillOnlyId);
                end
                if effBCenterObj ~= nil then
                    FightMgr.addSkeletonEvent(effBCenterObj:getSkeletonAnimation(), fighter.fighterId, target.fighterId, skillData.f_SkillID, skillShow, skillOnlyId);
                end
                FightMgr.addSkeletonEvent(fighter:getSkeletonAnimation(), fighter.fighterId, target.fighterId, skillData.f_SkillID, skillShow, skillOnlyId);
                fighter:playSkillAction(skillShow, attackSpeed, skillOnlyId);
                Entity:playSkillAudio(fighter, skillShow);
                Entity:playCVSoundByName(fighter, skillShow);
                --FireEvent(Config.EventType.Fight_SupSkill_ui, 2);
            end
            --if not this.supSkillCutIn then

            --if flag then
            --if helpId == 0 then
            --this.cutInState = true;
            --this.supSkillCutIn = true;
            --
            --this.cutInFrame = this.frame;
            ----local duration = Entity:GetTableValue(skillShow, "f_BackGroundDuration");
            ----if duration and duration == "" then
            ----    duration = G.dataTable["t_skillshow"][tostring(skillShow.f_SkillID) .. "1"]["f_BackGroundDuration"];
            ----end
            --this.cutInTime = (supBulletTime * this.supTimeScale[FightMgr.curTimeScale]) / EnumConst.THOUSANDTH;
            --this.cutInFighterId = fighter.fighterId;
            --for i = 1, #this.effectTempCacheList do
            --    if this.effectTempCacheList[i] then
            --        this.effectTempCacheList[i]:pause();
            --    end
            --end
            --fighter:playBackGroundFullScreen(skillShow, supBulletTime / EnumConst.THOUSANDTH);
            --this.supSkillTempTime = FightMgr.curTimeScale;
            --FightMgr.curTimeScale = 1 * this.supTimeScale[FightMgr.curTimeScale];
            --Time.timeScale = FightMgr.curTimeScale;
            --FireEvent(Config.EventType.Fight_SupSkill_Show, 2, helpManShow);  --出现替补\
            --else
            fighter:playBackGroundFullScreen(skillShow);
            --this.supSkillTempTime = FightMgr.curTimeScale;
            helpManShow()
            --end

            --else
            --end

            --end
        else
            if showType == EnumConst.AttackShowType.MOVE then
                local value = {};
                value.attackShowDuration = attackShowDuration / EnumConst.THOUSANDTH;
                value.attackMoveSpeed = attackMoveSpeed / EnumConst.TEN_THOUSANDTH;
                if flip then
                    value.attackDirection = Vector3(-1, 0, 0);
                else
                    value.attackDirection = Vector3(1, 0, 0);
                end
                fighter:setAttackShowType(showType, value);
            elseif showType == EnumConst.AttackShowType.Back then
                local value = {};
                value.attackShowDuration = attackShowDuration / EnumConst.THOUSANDTH;
                value.attackMoveSpeed = attackMoveSpeed / EnumConst.TEN_THOUSANDTH;
                if flip then
                    value.attackDirection = Vector3(1, 0, 0);
                else
                    value.attackDirection = Vector3(-1, 0, 0);
                end
                fighter:setAttackShowType(showType, value);

            elseif showType == EnumConst.AttackShowType.SPRINT or showType == EnumConst.AttackShowType.SPRINT_POS then
                if not actionPos then
                    logMy('客户端与服务端版本不一致，冲刺存在异常', skillShow.f_SkillID)
                    actionPos = target:getPosition()
                else
                    actionPos = Vector3(actionPos.x, 300, actionPos.y)
                end

                local duration = (sprintEndTime - this.frame) * defaultFrame;

                target.position = target:getPosition();
                local isRotation = true;--是否旋转角度进行冲锋
                flip = getRoleFlip(fighter, target);

                local dir = target:getPosition() - fighter:getPosition();
                if skillShow.f_SkillShowType == 5--[[定点冲刺]] then
                    actionPos = Vector3(actionPos.x, 300, actionPos.z)
                    dir = actionPos - fighter:getPosition();
                    --actionPos = skillFixedPos;
                    isRotation = false;
                    if math.abs(dir.x) > 0.01 then
                        flip = dir.x < 0;
                    else
                        local centerPos = (EnumConst.FIGHT_INNER_ROUND[1][1] + EnumConst.FIGHT_INNER_ROUND[2][1]) / 2;
                        flip = centerPos > fighter:getPosition().x;
                    end

                end
                if checkOut(target, EnumConst.FIGHT_INNER_ROUND) then
                    dir = actionPos - fighter:getPosition();
                end
                local vDir = dir.normalized; --Vector3.Normalize(dir);
                local distance = dir.magnitude;
                distance = distance - ((target.shape.x + fighter.shape.x) * 1);
                fighter:setFlip(flip);

                --如果距离太小，就不冲锋了
                if distance > 0.01 or skillShow.f_SkillShowType == 5 then
                    local value = {};
                    --if distance < 0.01 then
                    --    --定向冲锋反了
                    --    flip = false;
                    --    fighter:setFlip(flip);
                    --end

                    local targetPos = actionPos;
                    value.attackMoveEnd = targetPos;
                    value.targetPos = target:getPosition();
                    if checkOut(target, EnumConst.FIGHT_INNER_ROUND) then
                        value.targetPos = targetPos;
                    end
                    local moveSpeed = skillData["f_Speed"] or 200000; --protect
                    --value.attackMoveSpeed = attackMoveSpeed / EnumConst.TEN_THOUSANDTH;
                    value.attackMoveSpeed = moveSpeed / EnumConst.TEN_THOUSANDTH;
                    value.attackDirection = vDir;
                    value.attackDuration = duration;
                    value.attackMoveDelayTime = showValue / EnumConst.TEN_THOUSANDTH; --1.5;
                    value.isRotation = isRotation;
                    --value.attackMoveSpecialEffect = {afterimage = 1, interevalTime = 0.05, disappearTime = 0.1, color = {}, time = 0};

                    --logMy('fighter:setAttackShowType', showType, value);
                    fighter:setAttackShowType(showType, value);
                else
                    fighter.timeScale = FightMgr.curTimeScale;
                end

            elseif showType == EnumConst.AttackShowType.TARGETEFFECT then
            elseif showType == EnumConst.AttackShowType.CURVE then
            elseif showType == EnumConst.AttackShowType.TriggerHit then
            elseif showType == EnumConst.AttackShowType.Protect then
                local distance = EnumConst.TEN_THOUSANDTH;
                local enemy = nil;
                local targetPos;
                for i = 1, #this.fighterList do
                    local _fighter = this.fighterList[i];
                    if _fighter.teamIndex ~= target.teamIndex then
                        local temp = Vector3.Distance(target:getPosition(), _fighter:getPosition());
                        if temp > distance then
                            distance = temp;
                            enemy = _fighter;
                        end
                    end
                end

                --// 2.计算最佳位置
                local x = 0;
                if enemy ~= nil then
                    local dir = 0;
                    local flip1 = getRoleFlip(target, enemy);
                    if flip1 then
                        dir = -1;
                    else
                        dir = 1;
                    end
                    if Mathf.Abs(target:getPosition().x - enemy:getPosition().x) > (target.shape.x + fighter.shape.x) / 2 then
                        x = target:getPosition().x + dir * (target.shape.x + fighter.shape.x) / 2;
                    else
                        x = target:getPosition().x + dir * (target:getPosition().x - enemy:getPosition().x) / 2;
                    end
                    targetPos = Vector3(x, target:getPosition().y, target:getPosition().z);
                end
                --fighter:setPosition(targetPos);

                local value = {};
                local vDir = Vector3.Normalize(targetPos - fighter:getPosition());
                local fDistance = Vector3.Distance(targetPos, fighter:getPosition());
                value.attackMoveEnd = targetPos;--fDistance/(attackMoveSpeed/EnumConst.TEN_THOUSANDTH);
                value.attackMoveSpeed = attackMoveSpeed / EnumConst.TEN_THOUSANDTH;
                value.attackDirection = vDir;
                fighter:setAttackShowType(showType, value);
            elseif showType == EnumConst.AttackShowType.Flash then
                local targetPos = target:getPosition();
                if flip then
                    targetPos = Vector3(targetPos.x + showValue / EnumConst.TEN_THOUSANDTH, targetPos.y, targetPos.z);
                else
                    targetPos = Vector3(targetPos.x - showValue / EnumConst.TEN_THOUSANDTH, targetPos.y, targetPos.z);
                end
                fighter:setPosition(targetPos);
                local value = {};
                fighter:setAttackShowType(showType, value);
            elseif showType == EnumConst.AttackShowType.FullScreen then
                local oldPos = fighter:getPosition();
                local targetPos = Vector3(307.5, 300, 290);
                --log("================old" .. oldPos.x);
                fighter:setPosition(targetPos);
                local value = {};
                value.attackMoveEnd = oldPos;
                value.attackShowDuration = showValue / EnumConst.THOUSANDTH;
                fighter:setAttackShowType(showType, value);
            else
                fighter:setAttackShowType(EnumConst.AttackShowType.NONE, nil);
            end
            --释放技能特效
            local effFObj, effBObj = nil;
            local isLink = false
            if showType == EnumConst.AttackShowType.TARGETEFFECT then
                if skillData.f_SkillLabel and skillData.f_SkillLabel ~= "" and decodeJsonStrToTabel(skillData.f_SkillLabel)[1] == 2 then
                    --艾可抓人
                    isLink = true;
                end
                effFObj, effBObj = fighter:playSkill(target, skillShow, flip, 1, fighter, attackIsPos, skillFixedPos, isLink);
            else
                effFObj, effBObj = fighter:playSkill(fighter, skillShow, flip, 1, target, attackIsPos, skillFixedPos);
            end

            --场景特效
            local effFCenterObj, effBCenterObj = fighter:playCenter(fighter, skillShow);

            if effFObj ~= nil then
                FightMgr.addSkeletonEvent(effFObj:getSkeletonAnimation(), fighter.fighterId, target.fighterId, skillData.f_SkillID, skillShow, skillOnlyId);
                if showType == EnumConst.AttackShowType.SPRINT or showType == EnumConst.AttackShowType.SPRINT_POS then
                    --设置冲锋特效和冲锋时间同步
                    effFObj.duration = fighter.attackDuration;
                end
            end
            if effBObj ~= nil then
                FightMgr.addSkeletonEvent(effBObj:getSkeletonAnimation(), fighter.fighterId, target.fighterId, skillData.f_SkillID, skillShow, skillOnlyId);
                if showType == EnumConst.AttackShowType.SPRINT or showType == EnumConst.AttackShowType.SPRINT_POS then
                    effBObj.duration = fighter.attackDuration;
                end
            end
            if effFCenterObj ~= nil then
                FightMgr.addSkeletonEvent(effFCenterObj:getSkeletonAnimation(), fighter.fighterId, target.fighterId, skillData.f_SkillID, skillShow, skillOnlyId);
            end
            if effBCenterObj ~= nil then
                FightMgr.addSkeletonEvent(effBCenterObj:getSkeletonAnimation(), fighter.fighterId, target.fighterId, skillData.f_SkillID, skillShow, skillOnlyId);
            end
            FightMgr.addSkeletonEvent(fighter:getSkeletonAnimation(), fighter.fighterId, target.fighterId, skillData.f_SkillID, skillShow, skillOnlyId);
            if isLink then
                --钩子伸出
                local CacheRight = Vector3.right;
                FightMgr.hookCount = 0.20 / FightMgr.curTimeScale;
                local ani = effFObj.effGo.transform:Find("Animation")
                effFObj:bindLinkEffect(ani.gameObject:GetComponent(TSkeletonAnimation), true)
                local CacheNormalVec3 = Vector3.New(0, 0, 0)
                EffectFunctions.calcFollowPositionV2(effFObj.followInfo);
                effFObj.tempV3 = clone(effFObj.followInfo.position);
                this.linkFunc = function()
                    FightMgr.hookCount = FightMgr.hookCount - Time.deltaTime;
                    EffectFunctions.calcFollowPositionV2(effFObj.followInfo);
                    EffectFunctions.calcFollowPositionV2(effFObj.followInfo1);
                    local normalize = Vec3Sub(effFObj.followInfo1.position, effFObj.followInfo.position, CacheNormalVec3);
                    local lerp = Vec3Mul(normalize, (Time.deltaTime / 0.2), CacheNormalVec3);
                    Vec3Add(lerp, effFObj.tempV3, effFObj.tempV3);
                    local lw = effFObj.followInfo.position;
                    local rw = effFObj.tempV3;
                    if FightMgr.hookCount <= 0 then
                        rw = effFObj.followInfo1.position;
                    end
                    effFObj.rbone.position = rw;
                    effFObj.lbone.position = lw;
                    local detailY = (effFObj.lbone.position.y - effFObj.rbone.position.y);
                    local detailX = (effFObj.lbone.position.x - effFObj.rbone.position.x);
                    local pl = 0
                    if detailX ~= 0 and detailY ~= 0 then
                        pl = detailY / detailX
                    end
                    Util.Lua_SetLocalRotationXYZ(effFObj.skeletonAnimation.gameObject, 0, 0, math.atan(pl) * 180 / math.pi);
                    Util.Lua_SetGameObjectPositionXYZ(effFObj.effGo, (lw.x + rw.x) / 2, (lw.y + rw.y) / 2, (lw.z + rw.z) / 2)
                    if FightMgr.hookCount <= 0 or Mathf.Abs(effFObj.followInfo1.position.x - rw.x) < 0.5 or Mathf.Abs(effFObj.followInfo1.position.z - rw.z) < 0.5 then
                        --effFObj.skeletonAnimation:RegisterStateLuaUserFunction(function()
                        --添加连接
                        --end)
                        effFObj:playAction(effFObj.actionName);
                        effFObj.follow = false;
                        effFObj.linkEffect = true;
                        this.linkFunc = nil;
                    end
                end
            end

            fighter:playSkillAction(skillShow, attackSpeed, skillOnlyId);
            Entity:playSkillAudio(fighter, skillShow);
            Entity:playCVSoundByName(fighter, skillShow);
            --log("=============playSkillAction"..skillData.f_SkillID);

            local bulletTime = toNumber(skillData.f_BulletTime);
            local guideTime = toNumber(skillData.f_GuideTime);
            this.cutInSkillTime = guideTime / EnumConst.THOUSANDTH;

            --放大招（指定技能）时额外的特效
            local isOverHit = toNumber(skillShow.f_overhit);
            if isOverHit > 0 then
                local hitSkillShow = G.dataTable["t_skillshow"][tostring(isOverHit)];
                if hitSkillShow then
                    local fObj, bObj = fighter:playSkill(fighter, hitSkillShow, fighter.flip, 1, target);
                    --printError("===========", fighter.fighterId, isOverHit)
                end
                fighter:setAfterImageOne(skillShow.f_SkillID);
                --if fighter.teamIndex == 1 then
                if this.fightType == EnumConst.FightTypeConst.PerformBattle then
                    this.isSkillCutIn = true;
                    bulletTime = prepareTime[tostring(skillData.f_SkillID)];
                    if bulletTime == nil then
                        printError("error bulletTime" .. skillData.f_SkillID)
                    else
                        fighter.cutInTime = bulletTime * this.supTimeScale[this.curTimeScale] / EnumConst.THOUSANDTH;
                    end
                end

                --end
            end

            --if this.slowTimeDuration > 0 and bulletTime <= 0 and isOverHit > 0 and fighter.teamIndex == 1 then
            --    Time.timeScale = ClientFightManager.curTimeScale * this.slowTimeFactor;
            --    this.slowTimeState = true;
            --    this.slowTime = this.slowTimeDuration / EnumConst.THOUSANDTH;
            --end

            --if fighter.teamIndex == 1 then
            local helpManShow = nil;

            if bulletTime > 0 then
                --替补上场
                helpManShow = function()
                    --printError(skillShow.f_SkillName, skillShow.f_SkillID)
                    --fighter:playCutIn(skillShow);
                    local player = fighter;
                    if fighter.partnerModelId == "610" then
                        player = this.getEntityByModel("611", fighter.teamIndex);
                        fighter:setOrder(Config.SortingDefault.Role);
                    end
                    local cutInSkillShow = skillShow;
                    local addTime = supBulletTime;
                    if this.isSkillCutIn then
                        cutInSkillShow = G.dataTable["t_skillshow"]["103"]
                        addTime = bulletTime;
                        if this.fightType ~= EnumConst.FightTypeConst.PerformBattle then
                            fighter:playCutIn(skillShow);
                        end

                    end
                    player:playFullScreen(cutInSkillShow, addTime);
                    player:playSceneCardEffect(cutInSkillShow);
                    player:setOrder(Config.SortingDefault.Role);
                    --target:setOrder(Config.SortingDefault.Role);
                end
                if not this.isSkillCutIn then
                    bulletTime = bulletTime + supBulletTime;
                end

                this.cutInState = true;
                this.cutInFrame = this.frame;
                this.cutInTime = bulletTime * this.supTimeScale[this.curTimeScale] / EnumConst.THOUSANDTH;
                this.cutInFighterId = fighter.fighterId;
                --暂停动作
                for i = 1, #this.fighterList do
                    local _fighter = this.fighterList[i];
                    if _fighter.cutInTime == 0 and (not _fighter.isDeading) then
                        _fighter:PauseCurrentAction();
                        _fighter:PauseEffect();
                    end
                end
                --有支援技能有替补
                for i = 1, #this.effectTempCacheList do
                    if this.effectTempCacheList[i] then
                        this.effectTempCacheList[i]:pause();
                    end
                end
                helpManShow()
                if fighter.teamIndex == 1 and this.fightType ~= EnumConst.FightTypeConst.GuildBoss then
                    if this.battleInfo.mySupSkill and this.battleInfo.mySupSkill ~= 0 then
                        if not this.isSkillCutIn then
                            ubattletimer.delayCall(function()
                                FireEvent(Config.EventType.Fight_SupSkill_ui);
                            end, 1570)
                        end
                    end
                    this.supSkillTempTime = this.curTimeScale;
                    this.curTimeScale = this.supTimeScale[this.curTimeScale];
                    Time.timeScale = this.curTimeScale;
                    local skinId = this.skinId2Fighter[fighter.fighterId];
                    if skinId == nil then
                        skinId = 0;
                    end
                    if not this.isSkillCutIn then
                        AudioManager.PlayInteractionVoice(fighter.partnerModelId[_index], skinId, AudioManager.InteractionTagTable[17].Tag)
                        FireEvent(Config.EventType.Fight_SupSkill_Show, 0);  --出现替补
                    end
                else
                    this.supSkillTempTime = this.curTimeScale;

                end

            end
        end
        if skillData.f_UseSP > 0 and fighter.teamIndex == 1 and not this.cutInState then
            if this.fightType ~= EnumConst.FightTypeConst.PerformBattle then
                fighter:playCutIn(skillShow);
            end

            --for i = 1, #this.fighterList do
            --    local _fighter = this.fighterList[i];
            --    if fighter.fighterId == _fighter.fighterId then
            --        fighter:playFullScreen(skillShow);
            --        fighter:playCutIn(skillShow);
            --        fighter:setOrder(Config.SortingDefault.Role);
            --        target:setOrder(Config.SortingDefault.Role);
            --    end
            --end
        end
    end

    if skillShow.f_NextSkill ~= nil and skillShow.f_NextSkill ~= "" then
        --log("=============skillShow.f_NextSkill"..skillShow.f_NextSkill);
        local nextSkills = skillShow.f_NextSkill--decodeJsonStrToTabel();
        if nextSkills ~= nil and #nextSkills > 0 then
            --logMy('skillShow.f_NextSkill', skillShow.f_NextSkill, skillShow.f_SkillID)
            for i = 1, #nextSkills do
                local nextSkillId = nextSkills[i][1];
                local nextSkillDelay = nextSkills[i][2];
                --替补入场特效
                if skillShow.f_SkillID == 103 then
                    if fighter.teamIndex == 2 then
                        nextSkillId = 105;--我方104、敌方105
                    else
                        nextSkillDelay = nextSkills[i][2] - 300 + supBulletTime;
                    end
                end
                -- Util.WaitForSeconds(function()
                --     if fighter and fighter:getDeadState() then
                --         return ;
                --     end
                --     local nextSkillData = G.dataTable["t_skill"][tostring(nextSkillId)];
                --     local nextSkillShow = G.dataTable["t_skillshow"][tostring(nextSkillId)];
                --     if nextSkillShow ~= nil then
                --         --133101,勾子表现，暂时处理，特效和配置表就位后修改。===================
                --         if nextSkillShow.f_SkillID ~= 133101 and nextSkillShow.f_FlyFResource ~= nil and nextSkillShow.f_FlyFResource ~= "" and nextSkillShow.f_FlyFName ~= nil and nextSkillShow.f_FlyFName ~= "" then
                --             FightMgr.doFly(fighter, target, nextSkillData, nextSkillShow);
                --         else
                --             FightMgr.doAttack(fighter, target, nextSkillData, nextSkillShow, nil, skillFixedPos);
                --         end
                --     end
                -- end, nextSkillDelay / EnumConst.THOUSANDTH);
                local delayFunc = function(idx)
                    if fighter and fighter:getDeadState() or this.isEnd then
                        return
                    end
                    local nextSkillData = G.dataTable["t_skill"][tostring(nextSkillId)]
                    local nextSkillShow = G.dataTable["t_skillshow"][tostring(nextSkillId)]
                    if nextSkillShow ~= nil then
                        --133101,勾子表现，暂时处理，特效和配置表就位后修改。===================
                        if nextSkillShow.f_SkillID ~= 133101 and nextSkillShow.f_FlyFResource ~= nil and nextSkillShow.f_FlyFResource ~= "" and nextSkillShow.f_FlyFName ~= nil and nextSkillShow.f_FlyFName ~= "" then
                            FightMgr.doFly(fighter, target, nextSkillData, nextSkillShow, nil, skillOnlyId)
                        else
                            FightMgr.doAttack(fighter, target, nextSkillData, nextSkillShow, nil, skillFixedPos, nil, skillOnlyId)
                        end
                    end
                end
                local nextSkillData = G.dataTable["t_skill"][tostring(nextSkillId)]
                local nextSkillShow = G.dataTable["t_skillshow"][tostring(nextSkillId)]
                if nextSkillShow.f_SkillID == 104 or nextSkillShow.f_SkillID == 105 then
                    ubattletimer.delayCall(delayFunc, nextSkillDelay);
                else
                    local delayFuncTime = nextSkillDelay / FightMgr.curTimeScale;
                    this.addDelayFuncs(delayFunc, delayFuncTime);
                end
            end
        end
    end
end

--前端攻击表现
function FightMgr.doShowAttack(fighter, target, skillShow, attackSpeed, skillFixedPos, skillOnlyId, sprintEndTime)
    local attackIsPos = tonumber(skillShow.f_isFixedPoint) == 1;--是否是定点释放技能
    if skillShow.f_SkillShowType ~= nil and skillShow.f_SkillShowType ~= "" then
        local showType = toNumber(skillShow.f_SkillShowType);
        local flip = getRoleFlip(fighter, target);
        fighter:setFlip(flip);
        if showType == EnumConst.AttackShowType.MOVE then
        elseif showType == EnumConst.AttackShowType.Back then
        elseif showType == EnumConst.AttackShowType.SPRINT then
        elseif showType == EnumConst.AttackShowType.TARGETEFFECT then
        elseif showType == EnumConst.AttackShowType.CURVE then
        else
            fighter:setAttackShowType(EnumConst.AttackShowType.NONE, nil);
        end

        --释放技能特效
        local effFObj, effBObj = nil;
        if showType == EnumConst.AttackShowType.TARGETEFFECT then
            effFObj, effBObj = fighter:playSkill(target, skillShow, flip, 1, nil, attackIsPos, skillFixedPos);
        else
            effFObj, effBObj = fighter:playSkill(fighter, skillShow, flip, 1, nil, attackIsPos, skillFixedPos);
        end

        --场景特效
        local effFCenterObj, effBCenterObj = fighter:playCenter(fighter, skillShow);

        if effFObj ~= nil then
            FightMgr.addSkeletonEvent(effFObj:getSkeletonAnimation(), fighter.fighterId, target.fighterId, skillShow.f_SkillID, skillShow, skillOnlyId);
        end
        if effBObj ~= nil then
            FightMgr.addSkeletonEvent(effBObj:getSkeletonAnimation(), fighter.fighterId, target.fighterId, skillShow.f_SkillID, skillShow, skillOnlyId);
        end
        if effFCenterObj ~= nil then
            FightMgr.addSkeletonEvent(effFCenterObj:getSkeletonAnimation(), fighter.fighterId, target.fighterId, skillShow.f_SkillID, skillShow, skillOnlyId);
        end
        if effBCenterObj ~= nil then
            FightMgr.addSkeletonEvent(effBCenterObj:getSkeletonAnimation(), fighter.fighterId, target.fighterId, skillShow.f_SkillID, skillShow, skillOnlyId);
        end
        FightMgr.addSkeletonEvent(fighter:getSkeletonAnimation(), fighter.fighterId, target.fighterId, skillShow.f_SkillID, skillShow, skillOnlyId);
        fighter:playSkillAction(skillShow, attackSpeed);
        Entity:playSkillAudio(fighter, skillShow);
        Entity:playCVSoundByName(fighter, skillShow);
        --log("=============playSkillAction"..skillShow.f_SkillID);

        if skillShow.f_NextSkill ~= nil and skillShow.f_NextSkill ~= "" then
            --log("=============skillShow.f_NextSkill"..skillShow.f_NextSkill);
            local nextSkills = skillShow.f_NextSkill--decodeJsonStrToTabel(skillShow.f_NextSkill);
            if nextSkills ~= nil and #nextSkills > 0 then
                for i = 1, #nextSkills do
                    local nextSkillId = nextSkills[i][1];
                    local nextSkillDelay = nextSkills[i][2];

                    -- Util.WaitForSeconds(function()
                    --     if fighter and fighter:getDeadState() then
                    --         return ;
                    --     end
                    --     local nextSkillData = G.dataTable["t_skill"][tostring(nextSkillId)];
                    --     local nextSkillShow = G.dataTable["t_skillshow"][tostring(nextSkillId)];
                    --     if nextSkillShow ~= nil then
                    --         if nextSkillShow.f_FlyFResource ~= nil and nextSkillShow.f_FlyFResource ~= "" and nextSkillShow.f_FlyFName ~= nil and nextSkillShow.f_FlyFName ~= "" then
                    --             FightMgr.doFly(fighter, target, nextSkillData, nextSkillShow);
                    --         else
                    --             FightMgr.doAttack(fighter, target, nextSkillData, nextSkillShow);
                    --         end
                    --     end
                    -- end, nextSkillDelay / EnumConst.THOUSANDTH);
                    local delayCall = function()
                        if fighter and fighter:getDeadState() then
                            return
                        end
                        local nextSkillData = G.dataTable["t_skill"][tostring(nextSkillId)]
                        local nextSkillShow = G.dataTable["t_skillshow"][tostring(nextSkillId)]
                        if nextSkillShow ~= nil then
                            if nextSkillShow.f_FlyFResource ~= nil and nextSkillShow.f_FlyFResource ~= "" and nextSkillShow.f_FlyFName ~= nil and nextSkillShow.f_FlyFName ~= "" then
                                FightMgr.doFly(fighter, target, nextSkillData, nextSkillShow, nil, skillOnlyId)
                            else
                                FightMgr.doAttack(fighter, target, nextSkillData, nextSkillShow, nil, nil, nil, skillOnlyId)
                            end
                        end
                    end;
                    local delayCallTime = nextSkillDelay / FightMgr.curTimeScale;
                    this.addDelayFuncs(delayCall, delayCallTime);


                end
            end
        end
    end
end

--子弹
function FightMgr.doFly(fighter, target, skillData, skillShow, skillFixedPos, commentInfo)
    local skillOnlyId = commentInfo.skillOnlyId;
    local endTime = commentInfo.endTime;
    --fightShowLog("[DoGFly]fighterId:"..fighter.fighterId.."skillId:"..skillShow.f_SkillID);
    local attackIsPos = tonumber(skillShow.f_isFixedPoint) == 1;--是否是定点释放技能
    if skillShow.f_SkillShowType ~= nil and skillShow.f_SkillShowType ~= "" and skillData ~= nil then
        local flip = getRoleFlip(fighter, target);
        local showType = toNumber(skillShow.f_SkillShowType);

        local bulletTime = toNumber(skillData.f_BulletTime);
        local guideTime = toNumber(skillData.f_GuideTime);
        this.cutInSkillTime = guideTime / EnumConst.THOUSANDTH;

        Entity:playSkillAudio(target, skillShow)

        local flyFunc = function()
            local skillIdAndOnly = skillShow.f_SkillID .. "_" .. skillOnlyId;
            local eventData = Spine.EventData.New(tostring(skillIdAndOnly));
            local fighterId = fighter.fighterId
            if commentInfo.realFighter then
                fighterId = commentInfo.realFighter;
            end
            eventData.Int = fighterId;
            eventData.Float = target.fighterId;
            eventData.String = "";
            this.skeletonAnimStateUserDataString[skillShow.f_SkillID] = skillShow
            local event = Spine.Event.New(0, eventData);
            event.Int = EnumConst.SpineEventType.HIT;
            UserDataEventDelegate(event, eventData);
            local event2 = Spine.Event.New(0, eventData);
            event2.Int = EnumConst.SpineEventType.DAMAGE;
            UserDataEventDelegate(event2, eventData);
            if showType == EnumConst.AttackShowType.BulletFlyShow then
                local effFObj, effBObj = Entity:playSkill(target, skillShow, flip, 1, nil, attackIsPos, skillFixedPos);
                if effFObj ~= nil then
                    FightMgr.addSkeletonEvent(effFObj:getSkeletonAnimation(), fighter.fighterId, target.fighterId, skillData.f_SkillID, skillShow, skillOnlyId);
                end
                if effBObj ~= nil then
                    FightMgr.addSkeletonEvent(effBObj:getSkeletonAnimation(), fighter.fighterId, target.fighterId, skillData.f_SkillID, skillShow, skillOnlyId);
                end
            end
        end

        --printError(skillShow.f_SkillID)
        if showType == EnumConst.AttackShowType.TARGETEFFECT then
            --if skillShow and skillShow.f_SkillID == 90100011 then
            --    printError("0000")
            --end
            local effFObj, effBObj = Entity:playSkill(target, skillShow, flip, 1, fighter, attackIsPos, skillFixedPos);
            if effFObj ~= nil then
                FightMgr.addSkeletonEvent(effFObj:getSkeletonAnimation(), fighter.fighterId, target.fighterId, skillData.f_SkillID, skillShow, skillOnlyId);
            end
            if effBObj ~= nil then
                FightMgr.addSkeletonEvent(effBObj:getSkeletonAnimation(), fighter.fighterId, target.fighterId, skillData.f_SkillID, skillShow, skillOnlyId);
            end

        elseif showType == EnumConst.AttackShowType.ATTACKEFFECT then
            local effFObj, effBObj = Entity:playSkill(fighter, skillShow, flip, 1, nil, attackIsPos, skillFixedPos);
            if effFObj ~= nil then
                FightMgr.addSkeletonEvent(effFObj:getSkeletonAnimation(), fighter.fighterId, target.fighterId, skillData.f_SkillID, skillShow, skillOnlyId);
            end
            if effBObj ~= nil then
                FightMgr.addSkeletonEvent(effBObj:getSkeletonAnimation(), fighter.fighterId, target.fighterId, skillData.f_SkillID, skillShow, skillOnlyId);
            end
        elseif showType == EnumConst.AttackShowType.CURVE then
            local dtime = 1000 / EnumConst.THOUSANDTH;
            dtime = dtime * FightMgr.curTimeScale;
            if skillShow.f_SkillShowValue ~= nil and skillShow.f_SkillShowValue ~= "" then
                --dtime = toNumber(skillShow.f_SkillShowValue)/EnumConst.THOUSANDTH;


                local showValueTbl = skillShow.f_SkillShowValue or {};
                local showValue = showValueTbl[1] or 0;
                dtime = showValue / EnumConst.THOUSANDTH;
            end

            local flip = getRoleFlip(fighter, target);
            local flyStartPos = fighter:getOffsetPosition(skillShow.f_FlyFPosition, flip);
            local hitPos = target:getOffsetPosition(skillShow.f_HitFPosition, flip);

            local flyDir = hitPos - flyStartPos;
            local vSpeed = Vector3.Normalize(flyDir);
            local distance = flyDir.magnitude;

            vSpeed = vSpeed * (distance / dtime);

            --Entity:playFly(fighter,skillShow,vSpeed,dtime,fighter_Pos,function()
            Entity:playFly(fighter, target, skillShow, speed, dtime, flyStartPos, flyFunc);
        elseif showType == EnumConst.AttackShowType.TriggerHit then
            local skillIdAndOnly = skillShow.f_SkillID .. "_" .. skillOnlyId;
            local eventData = Spine.EventData.New(tostring(skillIdAndOnly));
            eventData.Int = fighter.fighterId;
            eventData.Float = target.fighterId;
            eventData.String = "";
            this.skeletonAnimStateUserDataString[skillShow.f_SkillID] = skillShow
            local event = Spine.Event.New(0, eventData);
            event.Int = EnumConst.SpineEventType.DAMAGE;
            UserDataEventDelegate(event, eventData);
        elseif showType == EnumConst.AttackShowType.Arrow then
            local speed = (toNumber(skillData.f_Speed) / EnumConst.TEN_THOUSANDTH) * FightMgr.curTimeScale;
            local flip = getRoleFlip(fighter, target);

            local flyStartPos = fighter:getOffsetPosition(skillShow.f_FlyFPosition, flip);
            local hitPos = target:getOffsetPosition(skillShow.f_HitFPosition, flip);

            local flyDir = hitPos - flyStartPos;
            if flyDir.x > 0 then
                flip = false;
            else
                flip = true;
            end
            local vSpeed = Vector3.Normalize(flyDir);
            local distance = flyDir.magnitude;

            vSpeed = vSpeed * speed;
            local flyEndTime = endTime;
            if flyEndTime == nil then
                flyEndTime = distance / speed;
            end
            --Entity:playFly(fighter,skillShow,vSpeed,distance/speed,fighter_Pos,function()
            Entity:playFly(fighter, target, skillShow, speed, flyEndTime, flyStartPos, flyFunc, flip);
        elseif showType == EnumConst.AttackShowType.FullScreen then
            local effFCenterObj, effBCenterObj = fighter:playCenter(fighter, skillShow);
            if effBCenterObj ~= nil then
                FightMgr.addSkeletonEvent(effBCenterObj:getSkeletonAnimation(), fighter.fighterId, target.fighterId, skillShow.f_SkillID, skillShow, skillOnlyId);
            end
            if effFCenterObj ~= nil then
                FightMgr.addSkeletonEvent(effFCenterObj:getSkeletonAnimation(), fighter.fighterId, target.fighterId, skillShow.f_SkillID, skillShow, skillOnlyId);
            end

        else
            local speed = (toNumber(skillData.f_Speed) / EnumConst.TEN_THOUSANDTH) * FightMgr.curTimeScale;
            if speed == 0 then
                local effFObj, effBObj = Entity:playSkill(fighter, skillShow, flip, 1, nil, attackIsPos, skillFixedPos);
                if effFObj ~= nil then
                    FightMgr.addSkeletonEvent(effFObj:getSkeletonAnimation(), fighter.fighterId, target.fighterId, skillData.f_SkillID, skillShow, skillOnlyId);
                end
                if effBObj ~= nil then
                    FightMgr.addSkeletonEvent(effBObj:getSkeletonAnimation(), fighter.fighterId, target.fighterId, skillData.f_SkillID, skillShow, skillOnlyId);
                end
            else
                --子弹触发
                local flyStartPos = fighter:getOffsetPosition(skillShow.f_FlyFPosition, fighter.flip);
                local hitPos = target:getOffsetPosition(skillShow.f_HitFPosition, target.flip);
                local flyDir = hitPos - flyStartPos;
                local skillId = skillShow.f_SkillID;
                local skillIData = G.dataTable["t_skill"][tostring(skillId)];
                local flip = true;
                local zPos = -0.05;
                if flyDir.x > 0 then
                    flip = false;
                else
                    zPos = 0.05
                end
                if skillIData then
                    if skillIData.f_SkillOver == 3 and skillIData.f_SkillOut == 1 then
                        endTime = nil;
                        flyStartPos.z = flyStartPos.z + zPos;
                        flyDir = Vector3.New(skillFixedPos.x, flyStartPos.y, flyStartPos.z) - flyStartPos;
                    end
                end

                --logMy('flyDir = hitPos - flyStartPos', flyDir, hitPos, flyStartPos);
                local vSpeed = Vector3.Normalize(flyDir);
                local distance = flyDir.magnitude;
                local flyEndTime = distance / speed;
                vSpeed = vSpeed * speed;
                if endTime then
                    flyEndTime = ((endTime - this.frame) * defaultFrame);
                end
                local realFighter = nil;
                if commentInfo.realFighter then
                    realFighter = commentInfo.realFighter;
                end
                --Entity:playFly(fighter,skillShow,vSpeed,distance/speed,fighter_Pos,function()
                Entity:playFly(fighter, target, skillShow, speed, flyEndTime, flyStartPos, flyFunc, flip, realFighter, skillFixedPos);
            end
        end
    end
end

--受击
function FightMgr.doHit(fighter, target, skillBean, skillShow)

    if skillShow.f_HitShowType ~= nil and skillShow.f_HitShowType ~= "" then
        --logMy('doHit', target.fighterId, skillShow.f_HitShowType);

        local flip = getRoleFlip(fighter, target);
        local showType = toNumber(skillShow.f_HitShowType);
        local hitValue = skillShow.f_HitShowValue or {}--decodeJsonStrToTabel(skillShow.f_HitShowValue) or {};
        if showType == EnumConst.HitShowType.REPULSE then
            local distance = toNumber(hitValue[2]);
            local time = toNumber(hitValue[1]);
            if time == 0 then
                time = EnumConst.FIGHT_FRAME;
            end
            local value = {};
            value.hitShowDuration = time / EnumConst.THOUSANDTH;
            value.maxHitShowDuration = value.hitShowDuration;
            value.hitMoveSpeed = (distance / EnumConst.TEN_THOUSANDTH) / value.hitShowDuration;
            if flip then
                value.hitDirection = Vector3(-1, 0, 0);
            else
                value.hitDirection = Vector3(1, 0, 0);
            end
            --log("=====================REPULSE"..value.hitShowDuration.." "..value.hitMoveSpeed)
            target:setHitShowType(showType, value);
            target:setAniState(Config.AnimationState.HURT, nil, false, true);
            fighter:playHit(target, skillShow, flip);

        elseif showType == EnumConst.HitShowType.HITFLY then

            local value = {};
            value.hitShowDuration = 500 / EnumConst.THOUSANDTH; --time
            value.maxHitShowDuration = value.hitShowDuration;
            target:setHitShowType(showType, value);
            target:setAniState(Config.AnimationState.HITFLY, nil, false, true);
            fighter:playHit(target, skillShow, flip);

        elseif showType == EnumConst.HitShowType.PULL then
            --logMy('doHit', fighter.fighterId, target.fighterId, skillShow);

            local time = toNumber(hitValue[1]);
            if time == 0 then
                time = EnumConst.FIGHT_FRAME;
            end

            local value = {};
            value.hitShowDuration = time / EnumConst.THOUSANDTH;
            value.maxHitShowDuration = value.hitShowDuration;
            local dir = fighter:getPosition() - target:getPosition();
            local distance = dir.magnitude;
            value.hitDirection = dir.normalized;

            value.hitMoveSpeed = distance / value.hitShowDuration;

            target:setHitShowType(showType, value);
            target:setAniState(Config.AnimationState.HURT, nil, false, true);
            fighter:playHit(target, skillShow, flip);

        elseif showType == EnumConst.HitShowType.HITDOWN then
            --logMy('HITDOWN', target.fighterId, skillShow.f_HitShowType);

            target:setHitShowType(showType);
            target:setAniState(Config.AnimationState.HITFLY, nil, false, true);
            fighter:playHit(target, skillShow, flip);

        else
            target:setAniState(Config.AnimationState.HURT, nil, false, false);
            fighter:playHit(target, skillShow, flip);
        end
    end
end

function FightMgr.doHitByBuff(fighter, target, buffData)

    if buffData.f_BuffEffect ~= nil and buffData.f_BuffEffect ~= "" then
        --if buffData.f_BuffId == 293102 then
        --logMy('doHitByBuff', fighter.fighterId, target.fighterId, buffData.f_BuffEffect, buffData.f_BuffEffectValue);
        --end

        local flip = getRoleFlip(fighter, target);
        local showType = toNumber(buffData.f_BuffEffect);
        local hitValue = decodeJsonStrToTabel(buffData.f_BuffEffectValue);

        if showType == EnumConst.BuffHitShowType.HITFLY then

            --logMy('doHitByBuff HITFLY', fighter.fighterId, target.fighterId, buffData.f_BuffEffect, buffData.f_BuffEffectValue);

            --[[ local value = {};
             local time = toNumber(hitValue[1]);
             value.hitShowDuration = time / EnumConst.TEN_THOUSANDTH; --0.5

             target:setHitShowType(showType, value);
             target:setAniState(Config.AnimationState.HITFLY, nil, false, true);--]]
            --Entity:playHit(target,skillShow,flip);
        elseif showType == EnumConst.BuffHitShowType.HIDE then
            local hideHeadBar = hitValue == nil and 0 or toNumber(hitValue[1]);
            local hideTime = toNumber(buffData.f_BuffRound);
            local value = {};
            value.hideTime = hideTime / EnumConst.THOUSANDTH;
            value.hideHeadBar = hideHeadBar;
            target:setHitShowType(showType, value);
            target:setAniState(Config.AnimationState.HURT, nil, false, true);
        elseif showType == EnumConst.BuffHitShowType.STUN then
            local value = {};
            --printError(target.fighterId.."===="..buffData.f_BuffId)
            target:setHitShowType(showType, value);
            target:setAniState(Config.AnimationState.STUN, nil, true, true);
        end
    end
end

function FightMgr.doBuff(fighter, target, type, buffData, buffShow, buffServerId, buffOverlay, buffPoolType, buffPoolMax, buffPoolCurrent)

    if buffData then
        local buffId = buffData.f_BuffId;
        if type == EnumConst.BuffType.Add then
            if buffId >= 225100 and buffId <= 225500 then
                if buffId % 10 == 1 then
                    --变鸡
                    --防止变鸡时没把伤害打完，将伤害直接爆出来
                    local damageInfo = FightMgr.getDamageAfterCurrentFrame(target.fighterId, FightMgr.frame);
                    if damageInfo then
                        for i, v in pairs(damageInfo) do
                            local skillData = G.dataTable["t_skillshow"][tostring(v.skillId)];
                            if skillData.f_SkillOut ~= 1 then
                                --直接把没打完的伤害爆出来（基本是鞭尸
                                local damage = v.damage;
                                local damageType = v.damageType;
                                v.used = true;
                                fighter:damage(damageType, damage, true)
                            end
                        end
                    end
                    target:setActive(false);
                end
            end
        elseif type == EnumConst.BuffType.Del then
            if buffId >= 225100 and buffId <= 225500 then
                if buffId % 10 ~= 0 then
                    --变鸡
                    target:setActive(true);
                end
            end
        end
    end

    if type == EnumConst.BuffType.Add then
        FightMgr.doHitByBuff(fighter, target, buffData);
        target:AddBuff(buffData, buffShow, fighter, buffServerId);
        if buffPoolType == 2 and buffPoolMax and buffPoolCurrent then
            target:ChangeBuffPool(buffPoolType, buffPoolMax, buffPoolCurrent)
        end
    elseif type == EnumConst.BuffType.Del then
        if buffPoolType == 2 and buffPoolMax and buffPoolCurrent then
            target:ChangeBuffPool(buffPoolType, 0, 0)
        end
        target:RemoveBuff(buffData, buffShow, buffServerId, fighter);
    elseif type == EnumConst.BuffType.ChangeOverlay then
        target:ChangeBuffOverlay(buffShow, buffServerId, buffOverlay);
    elseif type == EnumConst.BuffType.ChangePool then
        target:ChangeBuffPool(buffPoolType, buffPoolMax, buffPoolCurrent);
        --local buffs = {};
        --for k,v in pairs(fighter.buffEffect) do
        --    table.insert(buffs, k);
        --end
        --logMy('ChangeBuffOverlay, fighter', buffServerId, buffs);
        --
        --buffs = {};
        --for k,v in pairs(target.buffEffect) do
        --    table.insert(buffs, k);
        --end
        --logMy('ChangeBuffOverlay, target', buffServerId, buffs);
    end
end

function FightMgr.entrance()
    if FightMgr.hasEntrance then
        return
    end
    this.hasEntrance = true;
    print("开始入场entrance", Time.realtimeSinceStartup)
    if FightMgr.fightType ~= EnumConst.FightTypeConst.INSTANCE then
        this.initPet();
    end
    this.initFighter(this.entranceInit);
    --主线关卡
    if FightMgr.fightType == EnumConst.FightTypeConst.DUNGEON then
        FightMgr.playAMBAudio()
    end

    local speed = GetPlayerPrefs("UIBattleMainSpeed" .. logicMgr.HeroManager.GetRoleInfo("playerId"));
    if tonumber(speed) == 1 then
        FightMgr.curTimeScale = FightMgr.timeScaleLv_2;
    elseif tonumber(speed) == 2 then
        FightMgr.curTimeScale = FightMgr.timeScaleLv_3;
    else
        FightMgr.curTimeScale = FightMgr.timeScaleEntranceLv_1;
    end
    Time.timeScale = FightMgr.curTimeScale;
    AudioManager.SetRTPCValue("game_speed", (100 / FightMgr.curTimeScale))
end

function FightMgr.PreEntrance()
    --this.initPet();
    if FightMgr.fightType ~= EnumConst.FightTypeConst.INSTANCE then
        this.initPet();
    end
    this.initFighter(this.PreEntranceInit);
end

function FightMgr.PreEntranceInit()

    this.preEntranceFinished = true
    if this.loadingFinished then
        if FightMgr.fightType == EnumConst.FightTypeConst.DUNGEON then
            FightMgr.playAMBAudio()
        end

        local speed = GetPlayerPrefs("UIBattleMainSpeed" .. logicMgr.HeroManager.GetRoleInfo("playerId"));
        if tonumber(speed) == 1 then
            FightMgr.curTimeScale = FightMgr.timeScaleLv_2;
        elseif tonumber(speed) == 2 then
            FightMgr.curTimeScale = FightMgr.timeScaleLv_3;
        else
            FightMgr.curTimeScale = FightMgr.timeScaleEntranceLv_1;
        end
        Time.timeScale = FightMgr.curTimeScale;
        AudioManager.SetRTPCValue("game_speed", (100 / FightMgr.curTimeScale))

        FightMgr.entranceInit()
    end
end

function FightMgr.PreEntranceLoadingFinished()

    this.loadingFinished = true
    if this.preEntranceFinished then
        if FightMgr.fightType == EnumConst.FightTypeConst.DUNGEON then
            FightMgr.playAMBAudio()
        end

        local speed = GetPlayerPrefs("UIBattleMainSpeed" .. logicMgr.HeroManager.GetRoleInfo("playerId"));
        if tonumber(speed) == 1 then
            FightMgr.curTimeScale = FightMgr.timeScaleLv_2;
        elseif tonumber(speed) == 2 then
            FightMgr.curTimeScale = FightMgr.timeScaleLv_3;
        else
            FightMgr.curTimeScale = FightMgr.timeScaleEntranceLv_1;
        end
        Time.timeScale = FightMgr.curTimeScale;
        AudioManager.SetRTPCValue("game_speed", (100 / FightMgr.curTimeScale))

        FightMgr.entranceInit()
    end
end

function FightMgr.entranceInit()
    local delayTime = 1;
    local moveOffset = 10;
    --if cameraMain ~= nil then
    --    local animator = cameraMain.transform:GetComponent("Animator");
    --    animator:SetTrigger("entrance");
    --    Util.WaitForSeconds(function ()
    --        animator:ResetTrigger("entrance");
    --    end,2);
    --end
    FightMgr.entranceInitCamera();

    for i = 1, #this.fighterList do
        local fighter = this.fighterList[i];
        fighter:init();
        if (fighter.roleObj ~= nil) then
            local r = fighter.roleObj.transform;
            local tempPosx, tempPosy, tempPosz = Util.Lua_GetLocalPositionXYZ(r, 0, 0, 0);
            if fighter.teamIndex == 1 then
                local beginPos = Vector3(tempPosx - moveOffset, tempPosy, tempPosz);
                local targetPos = Vector3(tempPosx, tempPosy, tempPosz);
                fighter:setPosition(beginPos);
                fighter:setRunPos(targetPos);
            else
                local beginPos = Vector3(tempPosx, tempPosy, tempPosz);
                fighter:setPosition(beginPos);
                fighter:setAniState(Config.AnimationState.IDLE);
            end
            if indexofTable(this.alternate, fighter.fighterId) <= 0 then
                fighter:setActive(true);
            end
        end
    end
    if this.pet_1 and this.pet_1.modelGO ~= nil then
        local r = this.pet_1.modelGO.transform;
        local tempPosx, tempPosy, tempPosz = Util.Lua_GetLocalPositionXYZ(r, 0, 0, 0);

        local beginPos = Vector3(tempPosx - moveOffset, tempPosy, tempPosz);
        local targetPos = Vector3(tempPosx, tempPosy, tempPosz);
        this.pet_1:setPosition(beginPos);
        this.pet_1:setRunPos(targetPos);

    end
    --if this.entranceTimer == nil then
    --    this.entranceTimer = Timer.New(this.onUpdateEntrance, 0.033, 9999, true);
    --else
    --    this.entranceTimer:Reset(this.onUpdateEntrance, 0.033, 9999, true);
    --end
    --this.entranceTimer:Start();

    if not this.entranceHandle then
        this.entranceHandle = UpdateBeat:Add(this.onUpdateEntrance, this);
    end

    this.startTime = Time.realtimeSinceStartup;
    FireEvent(Config.EventType.Fight_Init);
    FireEvent(Config.EventType.Fight_Update_BossHP);
    FireEvent(Config.EventType.Fight_Update_HeroHP);
    FireEvent(Config.EventType.Fight_Update_Time, Mathf.Floor(maxTime));

    --永劫之境，快速跳过，遇到12两关相同地图时，时序错误，背景黑屏
    local mapInstance = BattleSceneCacheResouce:GetMapInstance()
    if mapInstance then
        local stageId = MapManager.GetCurrentStage()
        local pos = nil;
        local mapCfg = MapManager.GetMapcfgByID(stageId);
        if FightMgr.fightType == EnumConst.FightTypeConst.DUNGEON and mapCfg then
            pos = mapCfg.f_BattleMapPos;
            mapInstance:SetActive(true)
        else
            mapInstance:SetActive(false)
        end
        BattleSceneCacheResouce:InitMapInstance(mapInstance, true, pos)
    end

    this.startGeneralUpdate();
end

function FightMgr.entranceInitCamera()
    --if cameraMain ~= nil then
    --    cameraMain.transform.position = Vector3(297.5, 314, 279.5);
    --end
    if cameraMainControllerParam then
        cameraMainControllerParam.transform.position = cameraMainControllerParam.positions[1];
        cameraMainControllerParam.time = 0;
        cameraMainControllerParam.done = false;
    end

    if cameraMain then
        local animator = cameraMain.transform:GetComponent("Animator");
        if animator then
            animator.enabled = false;
        end
    end

end

function FightMgr.onUpdateEntrance()
    if Time.deltaTime > 2 then
        return ;
    end
    for i = 1, #this.fighterList do
        local fighter = this.fighterList[i];
        fighter:onUpdate(Time.deltaTime);
    end
    if this.pet_1 then
        this.pet_1:onUpdate(Time.deltaTime);
    end

    this.entranceFinish = true;

    for i = 1, #this.fighterList do
        local fighter = this.fighterList[i];
        if fighter:getAniState() ~= Config.AnimationState.IDLE then
            this.entranceFinish = false;
            break ;
        end
    end

    if this.entranceFinish then
        local speed = GetPlayerPrefs("UIBattleMainSpeed" .. logicMgr.HeroManager.GetRoleInfo("playerId"));
        if tonumber(speed) == 1 then
            FightMgr.curTimeScale = FightMgr.timeScaleLv_2;
        elseif tonumber(speed) == 2 then
            FightMgr.curTimeScale = FightMgr.timeScaleLv_3;
        else
            FightMgr.curTimeScale = FightMgr.timeScaleLv_1;
        end
        Time.timeScale = FightMgr.curTimeScale;
        AudioManager.SetRTPCValue("game_speed", (100 / FightMgr.curTimeScale))

        for i = 1, #this.fighterList do
            local fighter = this.fighterList[i];
            fighter:onEntranceFinish();
        end

        --this.entranceTimer:Stop();
        if this.entranceHandle then
            UpdateBeat:Remove(this.onUpdateEntrance, this);
            this.entranceHandle = nil
        end
        --if this.isEdit == nil then
        this.stateBegin(true);
        FireEvent(Config.EventType.Fight_Begin);
        --end
        FightMgr.beginCommand();
    end

    FightMgr.onUpdateEntranceCamera(Time.deltaTime);

    if this.entranceFinish and cameraMainControllerParam then
        cameraMainControllerParam.transform.position = cameraMainControllerParam.positions[3];
    end
end

function FightMgr.onUpdateEntranceCamera(deltaTime)
    if cameraMainControllerParam and not cameraMainControllerParam.done then
        local time = cameraMainControllerParam.time + deltaTime;
        cameraMainControllerParam.time = time;

        --local i = 0;
        for i = 1, #cameraMainControllerParam.times - 1 do
            if time >= cameraMainControllerParam.times[i] and time < cameraMainControllerParam.times[i + 1] then

                --Mathf.Lerp(float a, float b, float t)
                local t = (time - cameraMainControllerParam.times[i]) / (cameraMainControllerParam.times[i + 1] - cameraMainControllerParam.times[i]);
                local p = Vector3.Lerp(cameraMainControllerParam.positions[i], cameraMainControllerParam.positions[i + 1], t);
                cameraMainControllerParam.transform.position = p;

                --logMy('onUpdateEntranceCamera', cameraMainControllerParam, i, t, cameraMainControllerParam.transform.position);
                break ;
            elseif time >= cameraMainControllerParam.times[#cameraMainControllerParam.times] then
                cameraMainControllerParam.transform.position = cameraMainControllerParam.positions[#cameraMainControllerParam.positions];
                cameraMainControllerParam.done = true;

                if cameraMain then
                    local animator = cameraMain.transform:GetComponent("Animator");
                    if animator then
                        animator.enabled = true;
                    end
                end
            end
        end --end for
    end --end if

end

function FightMgr.endCommand()
    utimer.delayCall(function()
        this.stopCommand();
    end, 800)
    Time.timeScale = 1;--战斗结束，加速停止，正常速显示胜利动画。
    --printError("加速停止了")
    UIBattleMain.removeEvent();
    this.linkFunc = nil;
    -- Util.WaitForSeconds(function()
    --     this.finishFight(this.fightResult == 1);
    -- end, 0.1);
    utimer.delayCall(function()
        this.finishFight(this.fightResult == 1)
    end, 100)

    if this.fightResult == 1 then
        -- Util.WaitForSeconds(function()
        --     this.endFinishFight();
        --     FireEvent(Config.EventType.Fight_Finish);
        -- end, 0.5);
        utimer.delayCall(function()
            this.endFinishFight()
            FireEvent(Config.EventType.Fight_Finish)
        end, 800)
    else
        -- Util.WaitForSeconds(function()
        --     this.endFinishFight();
        --     FireEvent(Config.EventType.Fight_Finish);
        -- end, 0.5);
        utimer.delayCall(function()
            this.endFinishFight()
            FireEvent(Config.EventType.Fight_Finish)
        end, 800)
    end

    --start finish fight timer
    this.startFinishFight();
    AudioManager.TryStopAMBSound()
end

function FightMgr.forceEndCommand()

    this.stopCommand();
    this.finishFight(this.fightResult == 1);
    this.endFinishFight();
    FireEvent(Config.EventType.Fight_Finish, true);
    this.destroy();
end

--结束后角色动作
function FightMgr.finishFight(victory)

    --Util.Log('finishFight  '..tostring(victory));

    for i = 1, #this.fighterList do
        local fighter = this.fighterList[i];
        if fighter.isWaitDeadDam then
            fighter:setDead(true);
        end
        if not fighter:getDeadState() then
            fighter:setHeadBar(false);
            if fighter.teamIndex == 1 then
                if victory then
                    --Util.Log('finishFight  VICTORY'..tostring(fighter.model));
                    fighter:setAniState(Config.AnimationState.VICTORY);
                else
                    --Util.Log('finishFight  IDLE'..tostring(fighter.model));
                    fighter:setAniState(Config.AnimationState.IDLE);
                end
            else
                fighter:setAniState(Config.AnimationState.IDLE);
            end
        end
    end

end

--win动画等需要在这里面被fighter:onUpdate切换 etc
function FightMgr.onUpdateFinishFight()

    for i = 1, #this.fighterList do
        local fighter = this.fighterList[i];
        fighter:onUpdate(Time.deltaTime);
    end

    --这里是他懒的再申请一个变量。entranceFinish容易造成误解。
    this.entranceFinish = true;
    for i = 1, #this.fighterList do
        local fighter = this.fighterList[i];
        if fighter:getAniState() ~= Config.AnimationState.IDLE then
            this.entranceFinish = false;
            break ;
        end
    end
    if this.entranceFinish then
        this.stateBegin(false);
    end
end

function FightMgr.startFinishFight()

    if this.finishFightTimer == nil then
        this.finishFightTimer = Timer.New(this.onUpdateFinishFight, 0.033, 9999, true);
    else
        this.finishFightTimer:Reset(this.onUpdateFinishFight, 0.033, 9999, true);
    end
    this.finishFightTimer:Start();

end

function FightMgr.endFinishFight()

    if this.finishFightTimer then
        this.finishFightTimer:Stop();
    end

    this.endGeneralUpdate();
    --printError("用时===", Time.realtimeSinceStartup - this.testTime)
    Util.ClearAfterimage();

    --HelperFunc.UnloadUnusedAssets(EnumConst.ClearType.Fight)
end

--temp 后面考虑重构
function FightMgr.startGeneralUpdate()

    if this.generaUpdateTimer == nil then
        this.generaUpdateTimer = Timer.New(this.generaUpdate, 0.033, 9999, true);
    else
        this.generaUpdateTimer:Reset(this.generaUpdate, 0.033, 9999, true);
    end
    this.generaUpdateTimer:Start();

end

function FightMgr.generaUpdate()

    for i = 1, #this.fighterList do
        local fighter = this.fighterList[i];
        --fighter:onUpdate(Time.deltaTime);
        fighter:updateEffect(Time.deltaTime);
    end

end

function FightMgr.endGeneralUpdate()

    if this.generaUpdateTimer then
        this.generaUpdateTimer:Stop();
    end
end
--获取最高输出的英雄Id
function FightMgr.GetMVPHeroId()

    local _heroModelId = -1
    local _heroModelData = nil;
    local _maxStatistics = -1
    local _maxAttack = -1
    local _maxAttackHeroId = -1
    local _maxHeal = -1
    local _maxHealHeroId = -1
    local _maxKillNum = -1
    local _maxKillNumHeroId = -1
    local _heroStatistics = -1
    local _battleRecord = BattlePlaybackManager.getBattleRecord()
    local data = {};
    local _heroData = this.getKillModelId();
    --for k, v in pairs(this.fighterMap) do
    --    if v.teamIndex == 1 and v.partnerModelId ~= nil and v.isHero and v.killNum ~= nil and v.killNum > _maxKillNum then
    --        _maxKillNum = v.killNum;
    --        _maxKillNumHeroId = tonumber(v.partnerModelId);
    --    end
    --end
    local _heroMap = {};
    for k, v in pairs(_heroData) do
        if _heroMap[v] == nil then
            _heroMap[v] = 0;
        end
        _heroMap[v] = _heroMap[v] + 1;
        if _heroMap[v] > _maxKillNum then
            _maxKillNum = _heroMap[v];
            _maxKillNumHeroId = v;
        end
        _heroStatistics = v;
    end
    if _heroStatistics > 0 and _heroStatistics < 200 then
        table.insert(data, { _heroStatistics, 3 }); -- 最后一击
    end
    if FightMgr.isRePlay then
        if this.lastHeroModelData then
            return this.lastHeroModelData[1], this.lastHeroModelData[2];
        else
            return _maxKillNumHeroId, 2;
        end
    end
    local heroNumDataList = {};
    _maxKillNum = 0;
    if _battleRecord and _battleRecord.noFight ~= 1 then
        local battleFormation = FightMgr.teamRest[1] == 2 and _battleRecord.defender or _battleRecord.attacker;
        if battleFormation then
            for index, value in ipairs(battleFormation.memberStats) do
                --table.insert(data, _battleRecord.attacker.members[index].partnerModelId);
                --_heroStatistics = tonumber(tostring(value.attack + value.beInjured + value.heal))
                --if _heroStatistics > _maxStatistics then
                --    _maxStatistics = _heroStatistics
                --    _heroModelId = _battleRecord.attacker.members[index].partnerModelId
                --end
                _heroStatistics = tonumber(tostring(value.killTimes)) or 0;
                if _heroStatistics > _maxKillNum then
                    _maxKillNum = _heroStatistics;
                    _maxKillNumHeroId = battleFormation.members[index].partnerModelId;
                end
                _heroStatistics = tonumber(tostring(value.attack)) or 0
                if _heroStatistics > _maxAttack then
                    _maxAttack = _heroStatistics;
                    _maxAttackHeroId = battleFormation.members[index].partnerModelId;
                end
                _heroStatistics = tonumber(tostring(value.heal)) or 0
                if _heroStatistics > _maxHeal then
                    _maxHeal = _heroStatistics;
                    _maxHealHeroId = battleFormation.members[index].partnerModelId;
                end
                local heroNumData = {};
                heroNumData.partnerModelId = battleFormation.members[index].partnerModelId;
                heroNumData.killNum = _heroMap[tonumber(heroNumData.partnerModelId)] or 0;
                heroNumData.attack = _heroStatistics;
                heroNumData.heal = _heroStatistics;
                table.insert(heroNumDataList, heroNumData);
            end
            table.insert(data, { _maxAttackHeroId, 0 });-- 伤害最高
            if _maxHeal > 0 then
                table.insert(data, { _maxHealHeroId, 1 }); -- 治疗最多
            end
            table.sort(heroNumDataList, function(a, b)
                if a.killNum ~= b.killNum then
                    return a.killNum > b.killNum;
                end
                if a.attack ~= b.attack then
                    return a.attack > b.attack;
                end
                return a.heal > b.heal;
            end);
            if #heroNumDataList > 0 then
                table.insert(data, { heroNumDataList[1].partnerModelId, 2 }); -- 击杀最多
            end
        end
    else
        if _maxKillNumHeroId > 0 then
            table.insert(data, { _maxKillNumHeroId, 2 });
        end
    end
    if #data > 0 then
        math.randomseed(tostring(os.time()):reverse():sub(1, 7));
        _heroModelData = data[math.random(#data)];
    end
    if _heroModelData == nil then
        _heroModelData = { tostring(logicMgr.HeroManager.GetRoleHeadID()), 0 };
    end
    this.lastHeroModelData = _heroModelData;
    return _heroModelData[1], _heroModelData[2];
end

function FightMgr.stateBegin(is)

    for k, v in pairs(this.fighterList) do
        v:stateBegin(is);
    end
end
function FightMgr.leaveRoundBattle(isShowUI, ignoreEnterBattle)

    local v;
    if this.endData == nil then
        v = nil;
    else
        v = this.endData.result;
    end
    --endBattle(v);
    this.endData = nil;
    this.AutoFight = false;
    FightMgr.stopCommand();
    FightMgr.destroy();

    closeUI(PanelNames.UIBattleMain);
    DestoryUI(PanelNames.UILoadingBattle)
    if isShowUI == nil then
        isShowUI = true
    end
    if isShowUI then
        showUI(PanelResNames.UIHeadMenu);
        showUI(PanelNames.UIBottom, ignoreEnterBattle);
    end
    --UIBottom.onSetBattle();
    --hasInit = false;

end
function FightMgr.InitRewards(items)

    this.resultItems = {};
    if items == nil then
        return
    end
    local data = {};
    local dataFlag = {};
    for _, v in pairs(items) do
        local num = tonumber(tostring(v.num))
        if num > 0 then
            if dataFlag[v.itemModelId] then
                data[dataFlag[v.itemModelId]].num = tonumber(tostring(data[dataFlag[v.itemModelId]].num)) + num
            else
                table.insert(data, v);
                dataFlag[v.itemModelId] = #data;
            end
        end
    end
    for k, v in pairs(data) do
        local itemModelId = v.itemModelId;
        local itemData;
        if logicMgr.ItemManager.IsEquip(itemModelId) then
            itemData = logicMgr.EquipManager.getEquipConstDatabyModelId(itemModelId);
        else
            itemData = logicMgr.ItemManager.getItemConstDatabyModelId(itemModelId);
        end
        if itemData then
            itemData["itemModelId"] = v.itemModelId;
            itemData["num"] = tonumber(tostring(v.num));
            table.insert(this.resultItems, itemData)
        else
            logError("[receiveBoss]can't find item or equip config by id:" .. itemModelId)
        end
    end
end

function FightMgr.InitExtraRewards(items)

    if items == nil then
        this.resultExtraItems = nil
        return
    end

    this.resultExtraItems = {}
    local data = {}
    local dataFlag = {}
    for _, v in pairs(items) do
        local num = tonumber(tostring(v.num))
        if num > 0 then
            if dataFlag[v.itemModelId] then
                data[dataFlag[v.itemModelId]].num = tonumber(tostring(data[dataFlag[v.itemModelId]].num)) + num
            else
                table.insert(data, v)
                dataFlag[v.itemModelId] = #data
            end
        end
    end
    for k, v in pairs(data) do
        local itemModelId = v.itemModelId;
        local itemData;
        if logicMgr.ItemManager.IsEquip(itemModelId) then
            itemData = logicMgr.EquipManager.getEquipConstDatabyModelId(itemModelId)
        else
            itemData = logicMgr.ItemManager.getItemConstDatabyModelId(itemModelId)
        end
        if itemData then
            itemData["itemModelId"] = v.itemModelId
            itemData["num"] = tonumber(tostring(v.num))
            table.insert(this.resultExtraItems, itemData)
        else
            logError("[receiveBoss]can't find item or equip config by id:" .. itemModelId)
        end
    end
end

function FightMgr.closeFight(fightType, isSkip)

    if fightType == EnumConst.FightTypeConst.Expedition then
        --UIBottom.enterAdventure()

        logicMgr.UIShowManager.ShowExpeditionViewImmediate()
    elseif fightType == EnumConst.FightTypeConst.ARENA then
        this.leaveRoundBattle(true, true)
        UIBottom.enterAdventure()
        if not this.isRePlay then
            showUI(PanelResNames.UIArenaMainEnter);
            local formation_type = logicMgr.BattlePlaybackManager.GetFormationType()
            local arena_type = EnumConst.ArenaBattleType.Normal
            if formation_type and formation_type == EnumConst.FormationType.CrossArenaAtk then
                arena_type = EnumConst.ArenaBattleType.Cross
            elseif formation_type and formation_type == EnumConst.FormationType.TeamCrossArenaAtk then
                arena_type = EnumConst.ArenaBattleType.TeamCross
            end
            showUI(PanelNames.UIArenaMain, arena_type)
            --else
            --    if isOpenUI(PanelNames.UIHeadMenu) and isOpenUI(PanelNames.UIArenaMain) then
            --        closeUI(PanelNames.UIHeadMenu)
            --        local ui_arena_main = CtrlManager.GetCtrl(PanelNames.UIArenaMain)
            --        if ui_arena_main ~= nil then
            --            ui_arena_main.needShowHeadMenu = true
            --        end
            --    end
        end
    elseif fightType == EnumConst.FightTypeConst.TOWER then
        this.leaveRoundBattle(true, true)
        UIBottom.enterAdventure();
        if logicMgr.FuncOpenManager.isOpen(Config.FuncOpenType.TowerAdvaced, false) then
            showUI(PanelNames.UITowerMain)
        end
        local curTowerType = logicMgr.TowerManager.getClimbType();
        showUI(PanelNames.UIClimbTower, nil, false, curTowerType);
    elseif fightType == EnumConst.FightTypeConst.INSTANCE then
        this.leaveRoundBattle(true, true)
        UIBottom.enterAdventure()
        showUI(PanelNames.UIMythicDungonsPro)
    elseif fightType == EnumConst.FightTypeConst.TRIAL then
        this.leaveRoundBattle(true, true)
        UIBottom.enterAdventure()
        AudioManager.SetSwitch("Battle_SwitchGroup", "stormbay")
        if isOpenUI(PanelNames.UIAdventureMain) then
            local ui_adventure_main = CtrlManager.GetCtrl(PanelNames.UIAdventureMain)
            ui_adventure_main.OnClickAdventure5()
        else
            showUI(PanelNames.UIChaosTestNew);
        end
        --if logicMgr.ActiveManager.isHaveSevenDay() then
        --    logicMgr.HeroManager.showLocalityUIByName("ChaosTestShowSevenDayUI_", PanelNames.UISevenday);
        --end
    elseif fightType == EnumConst.FightTypeConst.FriendAttack then
        this.leaveRoundBattle(true, true)
        UIBottom.enterAdventure()
        showUI(PanelResNames.UIArenaMainEnter)
        showUI(PanelResNames.UIFriendWar)
    elseif fightType == EnumConst.FightTypeConst.RankBattle then
        this.leaveRoundBattle(true, true)
        AudioManager.SetSwitch("Battle_SwitchGroup", "origin")
        UIBottom.enterAdventure()
        showUI(PanelResNames.UIRankBattle)
    elseif fightType == EnumConst.FightTypeConst.FriendCompeteBattle then
        this.leaveRoundBattle()
        BattlePlaybackManager.doBattleBackFunc()
        BattlePlaybackManager.setBattleBackFunc()
    elseif fightType == EnumConst.FightTypeConst.GuildFriendCompeteBattle then
        this.leaveRoundBattle(true, true)
        UIBottom.enterTown();
        showUI(PanelNames.UIGuild);
    elseif fightType == EnumConst.FightTypeConst.GuildBoss then
        this.leaveRoundBattle(true, true)
        UIBottom.enterTown();
        showUI(PanelNames.UIGuild);
        showUI(PanelNames.UIGuildBoss);
    elseif fightType == EnumConst.FightTypeConst.RealMan then
        this.leaveRoundBattle(true, true);
        UIBottom.enterAdventure();
        logicMgr.RealManWarManager.OpenSoloBattle();
    elseif fightType == EnumConst.FightTypeConst.GuildBattlePlus then
        this.leaveRoundBattle(true, true);
        UIBottom.enterTown();
        logicMgr.GuildBattlePlusManager.setCanOpen(true);
        --unionWarPlusHandler.reqGuildBattleInfo(1)
        logicMgr.GuildBattlePlusManager.showUnionWarUI(logicMgr.GuildBattlePlusManager.getNowType())
    elseif fightType == EnumConst.FightTypeConst.DungeonEventPK then
        this.leaveRoundBattle()
        UIBottom.onSetBattle();
        logicMgr.DungeonRandomEventManager.ShowDungeonEventPKReward();
    elseif fightType == EnumConst.FightTypeConst.SoloChaosTest then
        UIBottom.onSetBattle();
        this.leaveRoundBattle(true, true)
        if logicMgr.SoloChaosTestManager.getOpenUI("UISoloChaosTest") then
            showUI(PanelNames.UISoloChaosTest, nil, logicMgr.SoloChaosTestManager.getOpenUI("UISoloChaosTest"));
        else
            showUI(PanelNames.UISoloChaosTestEnter, nil, logicMgr.SoloChaosTestManager.getNowActiveId());
        end
    elseif fightType == EnumConst.FightTypeConst.StoryBattle then
        this.leaveRoundBattle()
        UIBottom.onSetBattle();
        logicMgr.DungeonRandomEventManager.ShowDungeonEventPKReward();

    elseif fightType == EnumConst.FightTypeConst.LongJourneyHell then
        this.leaveRoundBattle();
        UIBottom.enterAdventure();
        logicMgr.LongJourneyHellManager.getLongJourneyHellServerData();
        --elseif fightType == EnumConst.FightTypeConst.PerformBattle then
        --    this.leaveRoundBattle()
        --    --UIBottom.onSetBattle();
        --    logicMgr.StoryMgr.ShowStoryById(5001013, EnumConst.StoryShowType.review, logicMgr.StoryMgr.callback)
    else
        this.leaveRoundBattle()
        UIBottom.onSetBattle();
    end
    showUI(PanelNames.UIScreenEffect)
    ArenaManager.setSomeBattleSkip(false);--跳过战斗标签设置回去

end
function FightMgr.saveBattleReport(fightCmdList)
    --fight log
    if this.saveReport then
        local fightLogName = tostring("BattleReport") .. '_' .. tostring(math.floor(Time.time)) .. '.log';
        printError(fightLogName)
        Util.SaveFile(fightLogName, getJsonStr(fightCmdList));
    end
end
---@param parent 对象的父物体
---@return 返回各战斗模式下，统一缩放，挂机和boss战
---因为各个战斗用的相机不同，所以，即便是相同的缩放比，也不一定表现一样。所以要分别配置
function FightMgr.getScaleParam(parent)

    if parent == panelMgr.BattleMain then
        return 0.8;--在挂机界面已经缩小后0.8后（在创建角色的时候传的），又一次缩放
    end
    return 0.9;
end

function FightMgr.playAMBAudio()

    local _currentChapterId = logicMgr.MapManager.GetCurrentChapterId()
    if _currentChapterId == 1 then
        AudioManager.Play(5001)
    elseif _currentChapterId == 2 then
        AudioManager.Play(5002)
    end
end

function is_include(value, tab)
    for k, v in ipairs(tab) do
        if v == value then
            return true
        end
    end
    return false
end

function IsMyHero(figherId, campIndex)
    for i = 1, #this.initFighterList do
        local fighterInfo = this.initFighterList[i]
        if fighterInfo.fighterId == figherId and fighterInfo.teamIndex == campIndex and fighterInfo.model ~= nil and not is_include(fighterInfo.fighterId, this.alternate) then
            return true
        end
    end
    return false
end

function FightMgr.GetNextSurviveFighter(campIndex)

    local f = {}

    for i = 1, #this.fighterMap do
        if IsMyHero(i, campIndex) and this.fighterMap[i] ~= nil and not this.fighterMap[i]:getDeadState() then
            table.insert(f, i)
        end
    end

    if #f > 0 then
        local index = math.random(1, #f)
        local value = f[index]
        f = nil
        return value
    end
    return 0
end

function FightMgr.GetFighterHP(index)

    if this.fighterMap[index] ~= nil and not this.fighterMap[index]:getDeadState() then
        return 1
    end
    return -1
end

function FightMgr.GetFighterOrder(index)

    if this.fighterMap[index] ~= nil and not this.fighterMap[index]:getDeadState() then
        return this.fighterMap[index]:GetOrderInLayer()
    end
    return 0
end

function FightMgr.GetFighterPosition(index)

    if this.fighterMap[index] ~= nil and not this.fighterMap[index]:getDeadState() then
        return this.fighterMap[index]:getPosition()
    end
    return nil
end

--BGM的困难度
function this.SetBGMSwitchByBattleType(fightType)
    local _difficultMode = "normal"
    local _result = this.BattleResultDic[fightType]
    if _result ~= nil and _result == false then
        _difficultMode = "boss"
    elseif fightType == EnumConst.FightTypeConst.DUNGEON then
        --如果当前挑战的关卡是最后一章，则播放Boss关音乐
        local _isEndChapterMap = MapManager.IsEndChapterMapId(tostring(logicMgr.MapManager.getNextStage()))
        if _isEndChapterMap then
            _difficultMode = "boss"
        end
    elseif fightType == EnumConst.FightTypeConst.TRIAL then
        _difficultMode = "boss"
    end
    AudioManager.SetSwitch("battle_type", _difficultMode)
end
--羁绊对话
function this.SetHeroSayData(myhelpId, myModelds_F, enemyModeIds_F)
    myModelds = {}
    keyIndex = {}
    for k, v in pairs(myModelds_F) do
        if tostring(v.partnerId) == tostring(myhelpId) then
            myModelds_F[k] = nil
        end
    end
    if myModelds_F[6] then
        myModelds_F[6] = nil
    end
    if enemyModeIds_F[6] then
        enemyModeIds_F[6] = nil
    end
    for _, v in ipairs(myModelds_F) do
        local dialogCfg = G.dataTable["t_herodialog"][tostring(v.partnerModelId)];
        if dialogCfg then
            local config = decodeJsonStrToTabel(dialogCfg.f_Dialog)
            if config and table.getn(config) > 0 then
                for _, v2 in pairs(config) do
                    for _, v3 in pairs(enemyModeIds_F) do
                        if v2[1] == tonumber(v3.partnerModelId) then
                            if not myModelds[tostring(v)] then
                                table.insert(keyIndex, v.partnerModelId)
                                myModelds[tostring(v.partnerModelId)] = v2
                            end
                        end
                    end
                end
            end
        end
    end
    if table.getn(myModelds) > 0 then
        local k = keyIndex[math.random(#keyIndex)]
        local num_r = math.random(1, 10)
        if num_r <= 3 then
            this.modelID, this.modeVal = k, myModelds[tostring(k)]
        else
            this.modelID, this.modeVal = nil, nil
        end
    else
        this.modelID, this.modeVal = nil, nil
    end
end
--load我方阵容
function this.SetMyTeam(info, helpID)
    this.loadContentId = {}
    if helpID and helpID ~= 0 then
        table.insert(this.loadContentId, helpID)
    end
    for _, v in pairs(info) do
        if v and v.partnerModelId then
            table.insert(this.loadContentId, v.partnerModelId)
        end
    end
end
function this.GetsloadContentId()
    return this.loadContentId
end
--添加延时
function this.addDelayFuncs(func, time, isBeCutIn)
    if not isBeCutIn then
        table.insert(this.delayFuncs, func);
        table.insert(this.delayFuncsTime, time / 1000);
    else
        table.insert(this.delayBeCutInFuncs, func);
        table.insert(this.delayBeCutInFuncsTime, time / 1000);
    end


end
--添加update方法
function this.addUpdateFuncs(func, time, isBeCutIn)
    if not isBeCutIn then
        table.insert(this.updateFunc, func);
        table.insert(this.updateFuncTime, time / 1000);
    else
        table.insert(this.updateBeCutInFunc, func);
        table.insert(this.updateBeCutInFuncTime, time / 1000);
    end

end

function this.setSkillEffectTimeScale()
    for i = 1, #this.fighterList do
        local fighter = this.fighterList[i];
        fighter:setSkillEffectTimeScale();
    end
end

function this.getEntityByFighterId(id)
    for i, v in pairs(this.initFighterList) do
        if v.fighterId == id then
            return v;
        end

    end
end
--检查当前战斗是否是Pve
function this.checkIsFightTypePVE(type)
    local flag = true;
    if type == nil then
        type = this.fightType;
    end
    for i, v in pairs(EnumConst.FightTypeConstPVP) do
        if v == type then
            return false;
        end
    end
    return flag;
end

function this.showResultUI(isSkip)
    --collectgarbage("collect")
    FightMgr.IsBattleFight = false
    local fType = FightMgr.fightType
    if isOpenUI(PanelNames.UIFuncOpenView) then
        closeUI(PanelNames.UIFuncOpenView);
    end
    Time.timeScale = 1;
    if FightMgr.isRePlay then
        if FightMgr.GetDungeonWinRePlay() and fType == EnumConst.FightTypeConst.DUNGEON then
            showUI(PanelNames.UIChapterRecord, true);
            showUI(PanelNames.UIBattleFail, function()
                FightMgr.closeFight(fType);
                if finishFunction ~= nil then
                    finishFunction();
                end
                logicMgr.GuideMgr.Resume()
                FireEvent(Config.EventType.StageRotate)
            end, { result = BattlePlaybackManager.getBattleResult(), items = {} });
            BattlePlaybackManager.setBattleRecord(BattlePlaybackManager.getOwnDungeonBattleRecord())
            FightMgr.SetRePlay(false)
            FightMgr.SetDungeonWinRePlay(false)
            return ;
        end
        logicMgr.GuideMgr.Pause()
        FightMgr.closeFight(fType);
        if finishFunction ~= nil then
            finishFunction();
        end
        FireEvent(Config.EventType.StageRotate)
        if fType == EnumConst.FightTypeConst.Plunder then
            --showUI(PanelNames.UIBigMap, true)
            -- showUI(PanelNames.UIRobRecord)
            if FightMgr.replay_type and FightMgr.replay_type == 2 then
                showUI(PanelNames.UIRevengeRecord, 1)
            end
        end
        FightMgr.SetRePlay(false)
        FightMgr.SetDungeonWinRePlay(false)
        return ;
    end

    local _battleRecord = BattlePlaybackManager.getBattleRecord()
    if _battleRecord and _battleRecord.noFight ~= 1 then
        --上阵英雄埋点
        if _battleRecord.attacker and _battleRecord.attacker.members then
            for index, hero in ipairs(_battleRecord.attacker.members) do
                local _myHeroDic = {}
                _myHeroDic.hero_uniqueid = tostring(hero.partnerId)
                _myHeroDic.hero_id = tostring(hero.partnerModelId)
                _myHeroDic.hero_level = tostring(hero.level)
                _myHeroDic.hero_star = tostring(hero.star)
                local _stats = _battleRecord.attacker.memberStats[index]
                _myHeroDic.attack = tostring(_stats.attack)
                _myHeroDic.be_injured = tostring(_stats.beInjured)
                _myHeroDic.heal = tostring(_stats.heal)
                _myHeroDic.fight_id = tostring(_battleRecord.fightId)
                TAManager.TrackByDictionary("battle_hero", _myHeroDic)
            end
        end

        if _battleRecord.attacker and _battleRecord.defender then
            if HeroManager.CompareMineId(_battleRecord.attacker.playerId) then
                this.UploadBattleRecord(_battleRecord, _battleRecord.attacker, _battleRecord.defender)
            else
                this.UploadBattleRecord(_battleRecord, _battleRecord.defender, _battleRecord.attacker)
            end
        end

        --更新战斗结果
        FightMgr.BattleResultDic[fType] = tonumber(_battleRecord.win) == 1
    end
    if fType == EnumConst.FightTypeConst.DUNGEON then
        --主线关卡埋点
        local _mainStageDic = {}
        _mainStageDic.fight_id = tostring(BattlePlaybackManager.FightId)
        _mainStageDic.nerf_parm = -1
        TAManager.TrackByDictionary("stage_battle_result", _mainStageDic)
    elseif fType == EnumConst.FightTypeConst.TOWER then
        -- 迷雾长廊埋点
        local _towerDic = {}
        _towerDic.tower_stage_id = tostring(logicMgr.TowerManager.getLastLayerId(1))
        _towerDic.fight_id = tostring(BattlePlaybackManager.FightId)
        TAManager.TrackByDictionary("tower_battle_result", _towerDic)
    elseif fType == EnumConst.FightTypeConst.ARENA then
        local resultDic = nil
        local formation_type = logicMgr.BattlePlaybackManager.GetFormationType()
        if formation_type and formation_type == EnumConst.FormationType.TeamCrossArenaAtk then
            resultDic = logicMgr.ArenaManager.resultDicCrossTeam
        elseif formation_type and formation_type == EnumConst.FormationType.CrossArenaAtk then
            resultDic = logicMgr.ArenaManager.resultDicCross
        else
            resultDic = logicMgr.ArenaManager.resultDic
        end
        --竞技场埋点
        local _arenaDic = {}
        _arenaDic.target_player_id = tostring(resultDic.target_player_id)
        _arenaDic.is_robot = resultDic.is_robot
        _arenaDic.delta_score = tostring(resultDic.delta_score)
        _arenaDic.delta_rank = tonumber(resultDic.delta_rank)
        _arenaDic.current_score = tostring(resultDic.current_score)
        _arenaDic.current_rank = tostring(resultDic.current_rank)
        _arenaDic.last_rank = tostring(resultDic.last_rank)
        _arenaDic.last_score = tostring(resultDic.last_score)
        _arenaDic.current_win_count = tostring(resultDic.current_win_count)

        if formation_type and formation_type == EnumConst.FormationType.TeamCrossArenaAtk then
            _arenaDic.my_level_id = tostring(resultDic.my_level_id)
            _arenaDic.target_level_id = tostring(resultDic.target_level_id)
            _arenaDic.target_server_id = tostring(resultDic.target_server_id)
            TAManager.TrackByDictionary("cross_team_arena_battle_result", _arenaDic)
        elseif formation_type and formation_type == EnumConst.FormationType.CrossArenaAtk then
            TAManager.TrackByDictionary("cross_arena_battle_result", _arenaDic)
        else
            TAManager.TrackByDictionary("arena_battle_result", _arenaDic)
            TAManager.UserSet("current_arena_rank", _arenaDic.current_rank)
        end
        --logicMgr.ArenaManager.resultDic = {}
        if BattlePlaybackManager.HasNextFight() then
            logicMgr.BattlePlaybackManager.ResetReceiveReport()
            logicMgr.BattlePlaybackManager.GotoFight(fType)
            BattlePlaybackManager.GotoNextFight(false)
            return
        end
    elseif fType == EnumConst.FightTypeConst.Expedition then
        --远征埋点
        local _expeditionDic = {}
        _expeditionDic.expedition_stage_id = logicMgr.ExpeditionMgr.GetCurStageId()
        _expeditionDic.fight_id = tostring(_battleRecord.fightId)
        _expeditionDic.expedition_end_time = tostring(logicMgr.ExpeditionMgr.endTime)
        TAManager.TrackByDictionary("expedition_battle_result", _expeditionDic)
    elseif fType == EnumConst.FightTypeConst.TRIAL then
        --混沌试炼
        local _trialsBossDic = {}
        _trialsBossDic.trials_id = tostring(logicMgr.ExpeditionMgr.GetCurStageId())
        _trialsBossDic.fight_id = tostring(_battleRecord.fightId)
        TAManager.TrackByDictionary("trials_boss_result", _trialsBossDic)
    elseif fType == EnumConst.FightTypeConst.GuildBattlePlus or fType == EnumConst.FightTypeConst.SoloChaosTest then
        if BattlePlaybackManager.HasNextFight() then
            logicMgr.BattlePlaybackManager.ResetReceiveReport()
            logicMgr.BattlePlaybackManager.GotoFight(fType)
            BattlePlaybackManager.GotoNextFight(false)
            return
        end
    end

    if fType == EnumConst.FightTypeConst.INSTANCE and BattlePlaybackManager.HasNextFight() then
        logicMgr.BattlePlaybackManager.ResetReceiveReport()
        logicMgr.BattlePlaybackManager.GotoFight(fType)
        BattlePlaybackManager.GotoNextFight(false)
        return
    elseif fType == EnumConst.FightTypeConst.GuildBoss then
        logicMgr.GuildManager.Track_bossBattelFinish(_battleRecord, curLevel)
    end
    logicMgr.MapManager.SetBattleBeforeMapId(MapManager.getMapId())
    logicMgr.GuideMgr.SetSoftGuideMapId(MapManager.getMapId())
    local battle_result = BattlePlaybackManager.getBattleResult()
    if fType == EnumConst.FightTypeConst.ARENA then
        local formation_type = logicMgr.BattlePlaybackManager.GetFormationType()
        if formation_type and formation_type == EnumConst.FormationType.TeamCrossArenaAtk then
            local win_count = FightMgr.cross_team_battle_data["win_count"] or 0
            if win_count >= 2 then
                battle_result = 1
            else
                battle_result = 0
            end
        end
    end
    if fType == EnumConst.FightTypeConst.GuildBattlePlus then
        local me, other = logicMgr.GuildBattlePlusManager.getAttackScore();
        if other <= 0 then
            battle_result = 1
        else
            battle_result = 0
        end
    end
    if fType == EnumConst.FightTypeConst.RealMan then
        if isOpenUI(PanelNames.UITeamBonus) then
            closeUI(PanelNames.UITeamBonus);
        end
        FightMgr.closeFight(fType);
    elseif battle_result == 1 or fType == EnumConst.FightTypeConst.TRIAL or
            fType == EnumConst.FightTypeConst.GuildBoss or fType == EnumConst.FightTypeConst.SoloChaosTest then
        if fType == EnumConst.FightTypeConst.PerformBattle then
            --表演战斗 直接跳过结算
            this.leaveRoundBattle(false)
            --UIBottom.onSetBattle();
            logicMgr.StoryMgr.ShowStoryById(5001013, EnumConst.StoryShowType.review, logicMgr.StoryMgr.callback)
            showUI(PanelNames.UIScreenEffect)
            if finishFunction ~= nil then
                finishFunction()
            end
        elseif not isOpenUI(PanelNames.UIBattleSuccess) then
            if fType == EnumConst.FightTypeConst.DUNGEON then
                logicMgr.GuideMgr.AddTrigger(GuideMgr.TriggerType.dungeonPass, MapManager.getMapId())
                logicMgr.GuideMgr.Pause()
            end
            logicMgr.GuideMgr.CheckSoftGuide()
            showUI(PanelNames.UIBattleSuccess, function()
                FightMgr.closeFight(fType, isSkip);
                if finishFunction ~= nil then
                    finishFunction(true);
                end
            end, { result = BattlePlaybackManager.getBattleResult(), items = FightMgr.resultItems });
            if fType == EnumConst.FightTypeConst.FriendAttack then
                --showUI(PanelNames.UIFight)
            end
        else
            if fType == EnumConst.FightTypeConst.StoryBattle then
                showUI(PanelNames.UIBattleSuccess, function()
                    FightMgr.closeFight(fType, isSkip);
                    if finishFunction ~= nil then
                        finishFunction(true);
                    end
                end, { result = BattlePlaybackManager.getBattleResult(), items = FightMgr.resultItems });
            end
        end
    else

        if fType == EnumConst.FightTypeConst.DUNGEON then
            logicMgr.GuideMgr.CheckSoftGuide()
        elseif fType == EnumConst.FightTypeConst.Expedition then
            logicMgr.GuideMgr.AddTrigger(GuideMgr.TriggerType.expeditionFailed)
        end
        showUI(PanelNames.UIBattleFail, function()
            FightMgr.closeFight(fType, isSkip)
            if finishFunction ~= nil then
                finishFunction(false)
            end
            --log("Util.WaitForSeconds closeFight");
        end, { result = BattlePlaybackManager.getBattleResult(), items = {} });
        if fType == EnumConst.FightTypeConst.FriendAttack then
            --showUI(PanelNames.UIFight)
        end

    end
    FightMgr.destroy();
    if fType ~= EnumConst.FightTypeConst.RealMan and
            fType ~= EnumConst.FightTypeConst.DarkStreet and
            fType ~= EnumConst.FightTypeConst.SoloChaosTest
    then
        UISpeed()
    end
end

-------通用战斗埋点 start
function this.UploadBattleRecord(_battleRecord, owninfo, enemyinfo)

    local _resultDic = {}
    _resultDic.battle_create_time = tostring(_battleRecord.createTime)
    _resultDic.source = tonumber(FightMgr.fightType)
    _resultDic.info_ex = -1
    _resultDic.fight_id = tostring(_battleRecord.fightId)
    _resultDic.is_win = tonumber(_battleRecord.win) == 1
    _resultDic.battle_log_id = -1
    _resultDic.duration = -1

    if FightMgr.fightType == EnumConst.FightTypeConst.ARENA then
        local formation_type = logicMgr.BattlePlaybackManager.GetFormationType()
        if formation_type and formation_type == EnumConst.FormationType.CrossArenaAtk then
            _resultDic.is_cross = 1
        elseif formation_type and formation_type == EnumConst.FormationType.TeamCrossArenaAtk then
            _resultDic.is_cross = 2
        else
            _resultDic.is_cross = 0
        end
    end

    _resultDic.own_battle_array = {}
    _resultDic.enemy_battle_array = {}
    if owninfo then
        if owninfo.members then
            _resultDic.own_battle_array = this.GetTrackStr(owninfo.members)
            _resultDic.m_pos1_hid = owninfo.members[1] and owninfo.members[1].partnerModelId
            _resultDic.m_pos2_hid = owninfo.members[2] and owninfo.members[2].partnerModelId
            _resultDic.m_pos3_hid = owninfo.members[3] and owninfo.members[3].partnerModelId
            _resultDic.m_pos4_hid = owninfo.members[4] and owninfo.members[4].partnerModelId
            _resultDic.m_pos5_hid = owninfo.members[5] and owninfo.members[5].partnerModelId
            _resultDic.m_pos6_hid = owninfo.members[6] and owninfo.members[6].partnerModelId

            _resultDic.m_pos1_lv = owninfo.members[1] and owninfo.members[1].level
            _resultDic.m_pos2_lv = owninfo.members[2] and owninfo.members[2].level
            _resultDic.m_pos3_lv = owninfo.members[3] and owninfo.members[3].level
            _resultDic.m_pos4_lv = owninfo.members[4] and owninfo.members[4].level
            _resultDic.m_pos5_lv = owninfo.members[5] and owninfo.members[5].level
            _resultDic.m_pos6_lv = owninfo.members[6] and owninfo.members[6].level

            _resultDic.m_pos1_star = owninfo.members[1] and owninfo.members[1].star
            _resultDic.m_pos2_star = owninfo.members[2] and owninfo.members[2].star
            _resultDic.m_pos3_star = owninfo.members[3] and owninfo.members[3].star
            _resultDic.m_pos4_star = owninfo.members[4] and owninfo.members[4].star
            _resultDic.m_pos5_star = owninfo.members[5] and owninfo.members[5].star
            _resultDic.m_pos6_star = owninfo.members[6] and owninfo.members[6].star
        end

        _resultDic.own_support_skill = owninfo.supportSkillId
    end

    if enemyinfo then
        if enemyinfo.members then
            _resultDic.enemy_battle_array = this.GetTrackStr(enemyinfo.members)

            _resultDic.e_pos1_hid = enemyinfo.members[1] and enemyinfo.members[1].partnerModelId
            _resultDic.e_pos2_hid = enemyinfo.members[2] and enemyinfo.members[2].partnerModelId
            _resultDic.e_pos3_hid = enemyinfo.members[3] and enemyinfo.members[3].partnerModelId
            _resultDic.e_pos4_hid = enemyinfo.members[4] and enemyinfo.members[4].partnerModelId
            _resultDic.e_pos5_hid = enemyinfo.members[5] and enemyinfo.members[5].partnerModelId
            _resultDic.e_pos6_hid = enemyinfo.members[6] and enemyinfo.members[6].partnerModelId

            _resultDic.e_pos1_lv = owninfo.members[1] and owninfo.members[1].level
            _resultDic.e_pos2_lv = owninfo.members[2] and owninfo.members[2].level
            _resultDic.e_pos3_lv = owninfo.members[3] and owninfo.members[3].level
            _resultDic.e_pos4_lv = owninfo.members[4] and owninfo.members[4].level
            _resultDic.e_pos5_lv = owninfo.members[5] and owninfo.members[5].level
            _resultDic.e_pos6_lv = owninfo.members[6] and owninfo.members[6].level

            _resultDic.e_pos1_star = owninfo.members[1] and owninfo.members[1].star
            _resultDic.e_pos2_star = owninfo.members[2] and owninfo.members[2].star
            _resultDic.e_pos3_star = owninfo.members[3] and owninfo.members[3].star
            _resultDic.e_pos4_star = owninfo.members[4] and owninfo.members[4].star
            _resultDic.e_pos5_star = owninfo.members[5] and owninfo.members[5].star
            _resultDic.e_pos6_star = owninfo.members[6] and owninfo.members[6].star
        end
        _resultDic.e_support_skill = enemyinfo.supportSkillId
    end

    TAManager.TrackByDictionary("battle_record", _resultDic)
end

function this.GetTrackStr(list)
    local ls = {}
    for index, hero in ipairs(list) do
        table.insert(ls, hero.partnerModelId)
    end

    table.sort(ls, function(a, b)
        return a < b
    end)

    local str = ""
    for i = 1, #ls do
        if i ~= #ls then
            str = str .. ls[i] .. ","
        else
            str = str .. ls[i]
        end
    end
    return str
end

function this.getEntityByModel(modelId, teamId)
    for k, v in pairs(this.fighterMap) do
        if teamId then
            if v.teamIndex == teamId and v.partnerModelId == modelId and v.isHero then
                return v;
            end
        else
            if v.partnerModelId == modelId and v.isHero then
                return v;
            end
        end
    end
    return nil;
end

function this.checkSoloBoss(modelId)
    if this.fightType == EnumConst.FightTypeConst.SoloChaosTest and tonumber(modelId) == SoloChaosTestManager.getBossId() then
        return true;
    end
    return false;
end
--自动战斗
function this.AutoGoFight(battleType, param)
    local _type = battleType or EnumConst.FightTypeConst.DUNGEON;
    if _type == EnumConst.FightTypeConst.DUNGEON then
        local nowStage = logicMgr.MapManager.getMapId();
        local mapConfig = G.dataTable["t_stage"][tostring(nowStage)];
        if FuncOpenManager.isOpen(Config.FuncOpenType.autoAttack, false) and FightMgr.isAuto and
                (not logicMgr.GuideMgr.HasGuidingInRankLevel(nowStage, mapConfig.f_NextStage)) and
                (not logicMgr.StoryMgr.HasStoryInRankLevel(nowStage, mapConfig.f_NextStage)) then
            if FightMgr.battleFunction then
                FightMgr.battleFunction()
                return true
            end
        end
    elseif _type == EnumConst.FightTypeConst.TOWER then
        if FuncOpenManager.isOpen(Config.FuncOpenType.autoAttack, false) and FightMgr.isAuto then
            local towerType = logicMgr.TowerManager.getClimbType();
            local curTowerInfo = logicMgr.TowerManager.returnTowerInfo(towerType);
            local curTowerlevel = tonumber(curTowerInfo["layerId"]);
            local towerCg = dataTable.getDataTableByStringId("t_tower", tostring((towerType - 1) * 10000 + curTowerlevel));
            if towerCg ~= nil then
                local battle_result = logicMgr.BattlePlaybackManager.getBattleResult();
                if battle_result == 1 then
                    local cfg_tower_type_item = dataTable.getDataTableByStringId("t_towertype", tostring(towerType));
                    local curTowerGroup = cfg_tower_type_item["f_Group"] or 1;
                    local curTowerLimit = cfg_tower_type_item["f_limit"] or 1;
                    if curTowerGroup ~= EnumConst.TowerType.Advanced or curTowerInfo.todayLayer < curTowerLimit then
                        return true;
                    end
                end
            end
        end
    elseif _type == EnumConst.FightTypeConst.StoryBattle then
        if FuncOpenManager.isOpen(Config.FuncOpenType.autoAttack, false) and FightMgr.isAuto then
            local nowStage = logicMgr.MapManager.GetStoryHardAutoMapId();
            local cfg = logicMgr.StoryHardManager.getDungeonTableDataById(nowStage);
            local battle_result = logicMgr.BattlePlaybackManager.getBattleResult();
            if cfg and (battle_result == 1 or param) then
                if logicMgr.BattlePlaybackManager.GetGroupBossIsOver() then
                    if cfg.f_NextStage ~= -1 and not logicMgr.StoryMgr.HasStoryInRankLevel(nowStage, cfg.f_NextStage, true)
                            and logicMgr.StoryHardManager.getPower() >= logicMgr.StoryHardManager.getBattlePower() then
                        local nextCfg = logicMgr.StoryHardManager.getDungeonTableDataById(cfg.f_NextStage);
                        if logicMgr.HeroManager.GetRoleLevel() >= nextCfg.f_CharacterLimit then
                            return true;
                        end
                    end
                else
                    local nexeGroupId = logicMgr.BattlePlaybackManager.GetGroupBossJoinGroupId(EnumConst.FightTypeConst.StoryBattle);
                    local data = logicMgr.FormationManager.GetFormation(EnumConst.FormationType.StoryDuplicate);
                    if data and data[nexeGroupId] and type(data[nexeGroupId]) == "table" and next(data[nexeGroupId]) then
                        for k, v in pairs(data[nexeGroupId]) do
                            if v ~= "0" and v ~= 0 then
                                return true;
                            end
                        end
                    end
                end
            end
        end
    end
    return nil
end
-------通用战斗埋点 end
-- function FightMgr.addJumpWord(jumpObj)
--     this.cacheJumpWord[jumpObj.displayObject.gameObject:GetInstanceID()] = jumpObj;
-- end
-- function FightMgr.removeJumpWord(jumpObj)
--     this.cacheJumpWord[jumpObj.displayObject.gameObject:GetInstanceID()] = nil;
-- end